From 4306b8424c85a8ab01502a8a00ab86a9a57844f9 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Cornilleau Date: Mon, 2 Jun 2025 18:35:10 +0200 Subject: [PATCH 1/3] Tezlink/Node: clean up modules in tezlink service There is no reason to search for Tezos_rpc in a dedicated Constant_service, which is temporary anyway --- .../bin_node/lib_dev/tezlink/tezos_services.ml | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml b/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml index 44074a22f8b8..7c9b7f03fc55 100644 --- a/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml +++ b/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml @@ -271,18 +271,16 @@ end (* TODO: #7875 Import from the protocol once it is exposed instead of copying it here. *) module Constants_services = struct - module RPC_path = Tezos_rpc.Path - module RPC_service = Tezos_rpc.Service - module RPC_query = Tezos_rpc.Query - let custom_root = - (RPC_path.(open_root / "context" / "constants") - : tezlink_rpc_context RPC_path.context) + let open Tezos_rpc in + (Path.(open_root / "context" / "constants") + : tezlink_rpc_context Path.context) let all = - RPC_service.get_service + let open Tezos_rpc in + Service.get_service ~description:"All constants" - ~query:RPC_query.empty + ~query:Query.empty ~output:Alpha_context.Constants.encoding custom_root end @@ -397,7 +395,7 @@ module Imported_services = struct unit, unit, Block_hash.t * Time.Protocol.t ) - Constants_services.RPC_service.t = + Tezos_rpc.Service.t = import_service Tezos_shell_services.Monitor_services.S.bootstrapped (* TODO: https://gitlab.com/tezos/tezos/-/issues/7965 *) @@ -411,7 +409,7 @@ module Imported_services = struct int32 option * Alpha_context.packed_operation * Chain_id.t * int, Alpha_context.packed_protocol_data * Imported_protocol.operation_receipt ) - Constants_services.RPC_service.t = + Tezos_rpc.Service.t = import_service Imported_protocol_plugin.RPC.Scripts.S.simulate_operation let monitor_heads : -- GitLab From 5533c416cfb476a21b57c4da5cd07c9b977afdeb Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Cornilleau Date: Mon, 2 Jun 2025 18:36:50 +0200 Subject: [PATCH 2/3] Tezlink/Node: issuance service --- .../lib_dev/tezlink/tezos_services.ml | 107 +++++++++++++++++- .../Alpha- Test the -describe endpoint.out | 6 + 2 files changed, 109 insertions(+), 4 deletions(-) diff --git a/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml b/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml index 7c9b7f03fc55..badaa64b577e 100644 --- a/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml +++ b/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml @@ -271,10 +271,8 @@ end (* TODO: #7875 Import from the protocol once it is exposed instead of copying it here. *) module Constants_services = struct - let custom_root = - let open Tezos_rpc in - (Path.(open_root / "context" / "constants") - : tezlink_rpc_context Path.context) + let custom_root : tezlink_rpc_context Tezos_rpc.Path.context = + Tezos_rpc.Path.(open_root / "context" / "constants") let all = let open Tezos_rpc in @@ -285,6 +283,102 @@ module Constants_services = struct custom_root end +(* Copied from src/proto_alpha/lib_plugin/adaptive_issuance_services.ml. *) +(* TODO: #7875 + It's exposed in proto_alpha, but not in the plugin of Rio. Import when we + move to a protocol that exposes it. *) +module Adaptive_issuance_services = struct + module Cycle = Protocol_types.Cycle + module Tez = Tezos_types.Tez + + 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; + dal_attesting_reward_per_shard : Tez.t; + seed_nonce_revelation_tip : Tez.t; + vdf_revelation_tip : Tez.t; + } + + let dummy_reward i = + { + cycle = i; + baking_reward_fixed_portion = Tez.one; + baking_reward_bonus_per_slot = Tez.one; + attesting_reward_per_slot = Tez.one; + dal_attesting_reward_per_shard = Tez.one; + seed_nonce_revelation_tip = Tez.one; + vdf_revelation_tip = Tez.one; + } + + let consensus_rights_delay = + Tezlink_constants.all_constants.parametric.consensus_rights_delay + + let dummy_rewards current_cycle = + List.init ~when_negative_length:[] (consensus_rights_delay + 1) (fun i -> + dummy_reward Cycle.(add (of_int32_exn current_cycle) i)) + + 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; + dal_attesting_reward_per_shard; + 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, + dal_attesting_reward_per_shard )) + (fun ( cycle, + baking_reward_fixed_portion, + baking_reward_bonus_per_slot, + attesting_reward_per_slot, + seed_nonce_revelation_tip, + vdf_revelation_tip, + dal_attesting_reward_per_shard ) -> + { + cycle; + baking_reward_fixed_portion; + baking_reward_bonus_per_slot; + attesting_reward_per_slot; + dal_attesting_reward_per_shard; + seed_nonce_revelation_tip; + vdf_revelation_tip; + }) + (obj7 + (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) + (req "dal_attesting_reward_per_shard" Tez.encoding)) + + let expected_issuance_path = + let open Tezos_rpc in + (Path.(open_root / "context" / "issuance" / "expected_issuance") + : tezlink_rpc_context Path.context) + + let expected_issuance = + let open Tezos_rpc in + Service.get_service + ~description: + "Returns the expected issued tez for the provided block and the next \ + 'consensus_rights_delay' cycles (in mutez)" + ~query:Query.empty + ~output:(Data_encoding.list expected_rewards_encoding) + expected_issuance_path +end + (* This is where we import service declarations from the protocol. *) module Imported_services = struct module Protocol_plugin_services = Imported_protocol_plugin.RPC.S @@ -544,6 +638,11 @@ let register_block_services ~l2_chain_id let*? block = check_block block in Backend.block_hash chain block) ~convert_output:Protocol_types.ethereum_to_tezos_block_hash + |> register + ~service:Adaptive_issuance_services.expected_issuance + ~impl:(fun _ () () -> + (* The mock assumes we stay in cycle 0 for now *) + Lwt.return @@ Adaptive_issuance_services.dummy_rewards Int32.zero) |> register (* TODO: https://gitlab.com/tezos/tezos/-/issues/7965 *) (* We need a proper implementation *) diff --git a/etherlink/tezt/tests/expected/evm_sequencer.ml/Alpha- Test the -describe endpoint.out b/etherlink/tezt/tests/expected/evm_sequencer.ml/Alpha- Test the -describe endpoint.out index 23b6ef1854cf..776f539ac54b 100644 --- a/etherlink/tezt/tests/expected/evm_sequencer.ml/Alpha- Test the -describe endpoint.out +++ b/etherlink/tezt/tests/expected/evm_sequencer.ml/Alpha- Test the -describe endpoint.out @@ -39,6 +39,9 @@ Available services: Access the counter of a contract, if any. - GET /tezlink/chains//blocks//context/contracts//manager_key Access the manager of an implicit contract. + - GET /tezlink/chains//blocks//context/issuance/expected_issuance + Returns the expected issued tez for the provided block and the + next 'consensus_rights_delay' cycles (in mutez) - GET /tezlink/chains//blocks//hash The block's hash, its unique identifier. - GET /tezlink/chains//blocks//header @@ -123,6 +126,9 @@ Available services: Access the counter of a contract, if any. - GET /chains//blocks//context/contracts//manager_key Access the manager of an implicit contract. + - GET /chains//blocks//context/issuance/expected_issuance + Returns the expected issued tez for the provided block and the + next 'consensus_rights_delay' cycles (in mutez) - GET /chains//blocks//hash The block's hash, its unique identifier. - GET /chains//blocks//header -- GitLab From dc5af9659d228fb62e3f41fd5f115344982572f2 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Cornilleau Date: Tue, 3 Jun 2025 11:48:55 +0200 Subject: [PATCH 3/3] Tezlink/tezt: test issuance service --- etherlink/tezt/tests/evm_sequencer.ml | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/etherlink/tezt/tests/evm_sequencer.ml b/etherlink/tezt/tests/evm_sequencer.ml index 4a3cd0de94d5..9473da85f910 100644 --- a/etherlink/tezt/tests/evm_sequencer.ml +++ b/etherlink/tezt/tests/evm_sequencer.ml @@ -591,6 +591,37 @@ let test_tezlink_protocols = ~error_msg:"Expected %R but got %L") ; unit +let test_tezlink_expected_issuance = + register_tezlink_test + ~title:"Test the mocked expected issuance rpc" + ~tags:["rpc"; "issuance"; "mock"] + @@ fun {sequencer; _} _protocol -> + (* call the rpc and parse the result *) + let rpc () = + let path = + "/tezlink/chains/main/blocks/head/context/issuance/expected_issuance" + in + let* res = + Curl.get_raw ~args:["-v"] (Evm_node.endpoint sequencer ^ path) + |> Runnable.run + in + return @@ JSON.parse ~origin:"curl" res + in + + let* res = rpc () in + let rewards = JSON.(res |> as_list) in + (* The mock assumes we stay in cycle 0 for now *) + Check.( + JSON.(List.hd rewards |-> "cycle" |> as_int = 0) + int + ~error_msg:"Expected %R but got %L") ; + + Check.( + (List.length rewards = 3) + int + ~error_msg:"Expected %R (consensus_rights_delay + 1) but got %L") ; + unit + let test_tezlink_balance = register_tezlink_test ~title:"Test of the balance rpc" @@ -13768,6 +13799,7 @@ let () = test_tezlink_manager_key [Alpha] ; test_tezlink_counter [Alpha] ; test_tezlink_protocols [Alpha] ; + test_tezlink_expected_issuance [Alpha] ; test_tezlink_monitor_heads [Alpha] ; test_tezlink_version [Alpha] ; test_tezlink_header [Alpha] ; -- GitLab