From ba6475b966d02d0f5143f94a5dba529f26684846 Mon Sep 17 00:00:00 2001 From: arnaud Date: Fri, 13 Jun 2025 10:31:31 +0200 Subject: [PATCH 1/5] Tezlink/Node: Introduce a storage represensation that'll be useful for Raw_services --- .../bin_node/lib_dev/tezlink/tezlink_mock.ml | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/etherlink/bin_node/lib_dev/tezlink/tezlink_mock.ml b/etherlink/bin_node/lib_dev/tezlink/tezlink_mock.ml index de140fe6bd85..93c6dfec64ad 100644 --- a/etherlink/bin_node/lib_dev/tezlink/tezlink_mock.ml +++ b/etherlink/bin_node/lib_dev/tezlink/tezlink_mock.ml @@ -34,6 +34,19 @@ let fitness = being replaced by actual data. *) let context = Context_hash.of_bytes_exn (Bytes.make 32 '\255') +let public_key_internal = + let pk_opt = + Tezos_crypto.Signature.Ed25519.Public_key.of_bytes_without_validation + (Bytes.make 32 '\000') + in + match pk_opt with None -> (* Unreachable *) assert false | Some pk -> pk + +let _public_key : Imported_protocol.Alpha_context.public_key = + Ed25519 public_key_internal + +let _public_key_hash : Imported_protocol.Alpha_context.public_key_hash = + Ed25519 (Tezos_crypto.Signature.Ed25519.Public_key.hash public_key_internal) + let contents : Alpha_context.Block_header.contents = { payload_hash = Imported_protocol.Block_payload_hash.zero; @@ -235,3 +248,69 @@ let version = network_version = Network_version.Internal_for_tests.mock (); commit_info = Some {commit_hash = ""; commit_date = ""}; } + +(* This module is a fake storage representation, the raw services gives access to the + real context. Unfortunately, some values are useless for Tezlink, so we don't want + to store them in the durable storage. So let's do their mock here *) +module Storage_repr = struct + module Cycle = struct + let delegate_sampler_state_encoding = + Imported_protocol.Sampler.encoding + Imported_protocol.Raw_context.consensus_pk_encoding + + let _create_sample_state ~consensus_pks = + Imported_protocol.Sampler.create consensus_pks + + let selected_stake_distribution_encoding = + Data_encoding.( + Variable.list + (obj2 + (req "baker" Signature.Public_key_hash.encoding) + (req "active_stake" Imported_protocol.Stake_repr.encoding))) + + type storage_cycle = { + selected_stake_distribution : + (Signature.public_key_hash * Imported_protocol.Stake_repr.t) list; + delegate_sampler_state : + Imported_protocol.Raw_context.consensus_pk Imported_protocol.Sampler.t; + } + + let _sampler_encoding = + let open Data_encoding in + conv + (fun {delegate_sampler_state; selected_stake_distribution} -> + ( (), + (), + delegate_sampler_state, + (), + (), + (), + (), + selected_stake_distribution, + () )) + (fun ( (), + (), + delegate_sampler_state, + (), + (), + (), + (), + selected_stake_distribution, + () ) -> {delegate_sampler_state; selected_stake_distribution}) + (obj9 + (req "already_denounced" empty) + (req "dal_already_denounced" empty) + (req "delegate_sampler_state" delegate_sampler_state_encoding) + (req "nonces" empty) + (req "pending_consensus_keys" empty) + (req "pending_staking_parameters" empty) + (req + "random_seed" + (constant + "0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8")) + (req + "selected_stake_distribution" + selected_stake_distribution_encoding) + (req "total_active_stake" empty)) + end +end -- GitLab From 90fa1b80a1fc24716bb2e645028d7b5b1e84b66c Mon Sep 17 00:00:00 2001 From: arnaud Date: Fri, 13 Jun 2025 10:31:01 +0200 Subject: [PATCH 2/5] Tezlink/Node: Add a Raw services module --- .../bin_node/lib_dev/tezlink/tezlink_mock.ml | 2 +- .../lib_dev/tezlink/tezos_services.ml | 48 ++++++++++++++++--- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/etherlink/bin_node/lib_dev/tezlink/tezlink_mock.ml b/etherlink/bin_node/lib_dev/tezlink/tezlink_mock.ml index 93c6dfec64ad..070a6a07f50d 100644 --- a/etherlink/bin_node/lib_dev/tezlink/tezlink_mock.ml +++ b/etherlink/bin_node/lib_dev/tezlink/tezlink_mock.ml @@ -275,7 +275,7 @@ module Storage_repr = struct Imported_protocol.Raw_context.consensus_pk Imported_protocol.Sampler.t; } - let _sampler_encoding = + let sampler_encoding = let open Data_encoding in conv (fun {delegate_sampler_state; selected_stake_distribution} -> diff --git a/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml b/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml index 0c0cc6ef35f3..99d84803dffc 100644 --- a/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml +++ b/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml @@ -6,6 +6,7 @@ (*****************************************************************************) include Tezlink_imports +open Tezlink_mock (** We add to Imported_protocol the mocked protocol data used in headers *) module Imported_protocol = struct @@ -165,6 +166,11 @@ let wrap conv impl p q i = types in the signature of the service [s]. *) let import_service s = Tezos_rpc.Service.subst0 s +(** [import_service_with_arg s] makes it possible to substitute new [prefix] + types in the signature of the service [s]. It also substitute the [param] + but keeps the last arg of the n-uplet intact. *) +let import_service_with_arg s = Tezos_rpc.Service.subst1 s + type block = Tezos_shell_services.Block_services.block type chain = Tezos_shell_services.Chain_services.chain @@ -300,6 +306,25 @@ module Adaptive_issuance_services = struct expected_issuance_path end +(* Raw services normally represents the context of the Tezos blockchain. + But because context in Tezlink is different, we need to mock some rpcs + to make Tzkt indexing works. *) +module Raw_services = struct + let custom_root : tezlink_rpc_context Tezos_rpc.Path.context = + Tezos_rpc.Path.(open_root / "context" / "raw" / "json") + + let cycle = + let open Tezos_rpc in + Service.get_service + ~description: + "Returns the cycle . This RPC is a mock as there's no cycle notion \ + in Tezlink and doesn't represent what's in the context of a block" + ~query:Query.empty + ~output:Storage_repr.Cycle.sampler_encoding + Imported_env.RPC_path.( + custom_root / "cycle" /: Imported_protocol.Cycle_repr.rpc_arg) +end + (* This is where we import service declarations from the protocol. *) module Protocol_plugin_services = Imported_protocol_plugin.RPC.S @@ -344,7 +369,7 @@ let contract_info : unit, Imported_protocol_plugin.Contract_services.info ) Tezos_rpc.Service.t = - Tezos_rpc.Service.subst1 Imported_protocol_plugin.Contract_services.S.info + import_service_with_arg Imported_protocol_plugin.Contract_services.S.info let balance : ( [`GET], @@ -354,7 +379,7 @@ let balance : unit, Tezos_types.Tez.t ) Tezos_rpc.Service.t = - Tezos_rpc.Service.subst1 Imported_protocol_plugin.Contract_services.S.balance + import_service_with_arg Imported_protocol_plugin.Contract_services.S.balance let manager_key : ( [`GET], @@ -364,8 +389,8 @@ let manager_key : unit, Protocol_types.Alpha_context.public_key option ) Tezos_rpc.Service.t = - let open Tezos_rpc in - Service.subst1 Imported_protocol_plugin.Contract_services.S.manager_key + import_service_with_arg + Imported_protocol_plugin.Contract_services.S.manager_key let counter : ( [`GET], @@ -375,8 +400,7 @@ let counter : unit, Protocol_types.Counter.t ) Tezos_rpc.Service.t = - let open Tezos_rpc in - Service.subst1 Imported_protocol_plugin.Contract_services.S.counter + import_service_with_arg Imported_protocol_plugin.Contract_services.S.counter let constants : ( [`GET], @@ -455,7 +479,7 @@ let get_storage_normalized : Imported_protocol.Script_ir_unparser.unparsing_mode, Alpha_context.Script.expr option ) Tezos_rpc.Service.t = - Tezos_rpc.Service.subst1 + import_service_with_arg Imported_protocol_plugin.RPC.Contract.S.get_storage_normalized let injection_operation : @@ -480,3 +504,13 @@ let preapply_operations : list ) Tezos_rpc.Service.t = import_service Block_services.S.Helpers.Preapply.operations + +let _raw_json_cycle : + ( [`GET], + tezlink_rpc_context, + tezlink_rpc_context * Imported_protocol.Cycle_repr.t, + unit, + unit, + Storage_repr.Cycle.storage_cycle ) + Tezos_rpc.Service.t = + import_service_with_arg Raw_services.cycle -- GitLab From 0529bddcc44292ae8a34a782f485cb34917b9e36 Mon Sep 17 00:00:00 2001 From: arnaud Date: Fri, 13 Jun 2025 10:32:09 +0200 Subject: [PATCH 3/5] Tezlink/Node: Register the raw_cycle service --- .../lib_dev/tezlink/tezlink_directory.ml | 22 +++++++++++++++++++ .../bin_node/lib_dev/tezlink/tezlink_mock.ml | 6 ++--- .../lib_dev/tezlink/tezos_services.ml | 2 +- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/etherlink/bin_node/lib_dev/tezlink/tezlink_directory.ml b/etherlink/bin_node/lib_dev/tezlink/tezlink_directory.ml index 9be4bf299ad5..aaca3d877acc 100644 --- a/etherlink/bin_node/lib_dev/tezlink/tezlink_directory.ml +++ b/etherlink/bin_node/lib_dev/tezlink/tezlink_directory.ml @@ -303,6 +303,28 @@ let build_block_static_directory ~l2_chain_id ops in Lwt_result_syntax.return (param#version, receipts)) + |> register + ~service:Tezos_services.raw_json_cycle + ~impl:(fun ({block; chain}, _cycle) () () -> + let open Tezlink_mock in + let*? _chain = check_chain chain in + let*? _block = check_block block in + let consensus_pk = + Imported_protocol.Raw_context. + { + delegate = public_key_hash; + consensus_pk = public_key; + consensus_pkh = public_key_hash; + } + in + let delegate_sampler_state = + Storage_repr.Cycle.create_sample_state + ~consensus_pks:[(consensus_pk, 200000000000L)] + in + let selected_stake_distribution = [] in + Lwt_result.return + Storage_repr.Cycle. + {delegate_sampler_state; selected_stake_distribution}) let register_block_info ~l2_chain_id (module Backend : Tezlink_backend_sig.S) (module Block_header : HEADER) base_dir = diff --git a/etherlink/bin_node/lib_dev/tezlink/tezlink_mock.ml b/etherlink/bin_node/lib_dev/tezlink/tezlink_mock.ml index 070a6a07f50d..e998d7a2be26 100644 --- a/etherlink/bin_node/lib_dev/tezlink/tezlink_mock.ml +++ b/etherlink/bin_node/lib_dev/tezlink/tezlink_mock.ml @@ -41,10 +41,10 @@ let public_key_internal = in match pk_opt with None -> (* Unreachable *) assert false | Some pk -> pk -let _public_key : Imported_protocol.Alpha_context.public_key = +let public_key : Imported_protocol.Alpha_context.public_key = Ed25519 public_key_internal -let _public_key_hash : Imported_protocol.Alpha_context.public_key_hash = +let public_key_hash : Imported_protocol.Alpha_context.public_key_hash = Ed25519 (Tezos_crypto.Signature.Ed25519.Public_key.hash public_key_internal) let contents : Alpha_context.Block_header.contents = @@ -258,7 +258,7 @@ module Storage_repr = struct Imported_protocol.Sampler.encoding Imported_protocol.Raw_context.consensus_pk_encoding - let _create_sample_state ~consensus_pks = + let create_sample_state ~consensus_pks = Imported_protocol.Sampler.create consensus_pks let selected_stake_distribution_encoding = diff --git a/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml b/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml index 99d84803dffc..25710f73b7c9 100644 --- a/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml +++ b/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml @@ -505,7 +505,7 @@ let preapply_operations : Tezos_rpc.Service.t = import_service Block_services.S.Helpers.Preapply.operations -let _raw_json_cycle : +let raw_json_cycle : ( [`GET], tezlink_rpc_context, tezlink_rpc_context * Imported_protocol.Cycle_repr.t, -- GitLab From 3e515bbd4907aea0073d47c9690d8ebf9b40c782 Mon Sep 17 00:00:00 2001 From: arnaud Date: Thu, 19 Jun 2025 17:52:21 +0200 Subject: [PATCH 4/5] Tezlink/regression: Update the describe regression --- .../evm_sequencer.ml/Alpha- Test the -describe endpoint.out | 6 ++++++ 1 file changed, 6 insertions(+) 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 3c830feef5ad..627d94184ac4 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 @@ -163,6 +163,10 @@ Available services: - GET /chains/main/blocks/head/context/issuance/expected_issuance Returns the expected issued tez for the provided block and the next 'consensus_rights_delay' cycles (in mutez) + - GET /chains/main/blocks/head/context/raw/json/cycle/ + Returns the cycle . This RPC is a mock as there's no cycle + notion in Tezlink and doesn't represent what's in the context of a + block - GET /chains/main/blocks/head/hash The block's hash, its unique identifier. - GET /chains/main/blocks/head/header @@ -189,6 +193,8 @@ Available services: Dynamic parameter description: + + A cycle integer A contract identifier encoded in b58check. -- GitLab From 272c17e42155d26c3cf0a51b45864cc2b2d10031 Mon Sep 17 00:00:00 2001 From: arnaud Date: Thu, 19 Jun 2025 14:26:17 +0200 Subject: [PATCH 5/5] Tezlink/Tezt: Append a tezt that verifies the answer of the rpc raw json cycle --- etherlink/tezt/tests/evm_sequencer.ml | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/etherlink/tezt/tests/evm_sequencer.ml b/etherlink/tezt/tests/evm_sequencer.ml index a481635f7268..7260f939cd1b 100644 --- a/etherlink/tezt/tests/evm_sequencer.ml +++ b/etherlink/tezt/tests/evm_sequencer.ml @@ -1454,6 +1454,33 @@ let test_tezlink_hash_rpc = ~error_msg:"Block hash should be different") ; unit +let test_tezlink_raw_json_cycle = + register_tezlink_test + ~title:"Test Tezlink raw json cycle rpc" + ~tags:["rpc"; "cycle"; "raw"] + @@ fun {sequencer; _} _protocol -> + let path_head = "/tezlink/chains/main/blocks/head/" in + let rpc_raw_json_cycle () = + let* res = + Curl.get_raw + ~args:["-v"] + (Evm_node.endpoint sequencer ^ path_head ^ "context/raw/json/cycle/0") + |> Runnable.run + in + return @@ JSON.parse ~origin:"curl_hash" res + in + let*@ _ = produce_block sequencer in + let* cycle_0 = rpc_raw_json_cycle () in + (* 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8 is the mock value + used for the ranom seed and never changes *) + Check.( + JSON.( + cycle_0 |-> "random_seed" |> as_string + = "0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8") + string + ~error_msg:"Unexpected random_seed field") ; + unit + module Protocol = struct include Protocol @@ -14078,6 +14105,7 @@ let () = test_tezlink_constants [Alpha] ; test_tezlink_produceBlock [Alpha] ; test_tezlink_hash_rpc [Alpha] ; + test_tezlink_raw_json_cycle [Alpha] ; test_tezlink_chain_id [Alpha] ; test_tezlink_bootstrapped [Alpha] ; test_fa_deposit_can_be_claimed [Alpha] ; -- GitLab