diff --git a/etherlink/bin_node/lib_dev/tezlink/tezlink_backend_sig.ml b/etherlink/bin_node/lib_dev/tezlink/tezlink_backend_sig.ml index f862f82aa4811f561f945a3261a9fbd7b5e18d41..4f62a4cb54d318072d2ed15244aaebdcdf5c50ad 100644 --- a/etherlink/bin_node/lib_dev/tezlink/tezlink_backend_sig.ml +++ b/etherlink/bin_node/lib_dev/tezlink/tezlink_backend_sig.ml @@ -28,7 +28,7 @@ module type S = sig val counter : [`Main] -> block_param -> Tezos_types.Contract.t -> Z.t tzresult Lwt.t - val header : [`Main] -> block_param -> L2_types.Tezos_block.t tzresult Lwt.t + val block : [`Main] -> block_param -> L2_types.Tezos_block.t tzresult Lwt.t val bootstrapped : unit -> (Ethereum_types.block_hash * Time.Protocol.t) tzresult Lwt.t diff --git a/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml b/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml index 44074a22f8b8db8230feb851b698bedb9db24058..ccf82c3623236d2d3be1e34936759f237d670105 100644 --- a/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml +++ b/etherlink/bin_node/lib_dev/tezlink/tezos_services.ml @@ -145,6 +145,29 @@ module Protocol_types = struct {chain_id; hash; shell; protocol_data} in return block_header + + let tezlink_block_to_raw_block_header block = + let open Result_syntax in + let* protocol_data = Protocol_data.get_mock_protocol_data in + let* shell = tezlink_block_to_shell_header block in + let raw_block_header : Block_services.raw_block_header = + {shell; protocol_data} + in + return raw_block_header + end + + module Block = struct + let tezlink_block_to_block_info ~l2_chain_id (version, block, chain) = + let open Result_syntax in + let* chain_id = tezlink_to_tezos_chain_id ~l2_chain_id chain in + let* hash = + ethereum_to_tezos_block_hash block.L2_types.Tezos_block.hash + in + let* header = Block_header.tezlink_block_to_raw_block_header block in + let block_info : Block_services.block_info = + {chain_id; hash; header; metadata = None; operations = []} + in + return (version, block_info) end module Level = struct @@ -424,6 +447,18 @@ module Imported_services = struct Block_hash.t * Block_header.t ) Tezos_rpc.Service.t = Tezos_shell_services.Monitor_services.S.heads + + let block_info : + ( [`GET], + tezlink_rpc_context, + tezlink_rpc_context, + < force_metadata : bool + ; metadata : [`Always | `Never] option + ; version : Tezlink_protocols.Shell_impl.version >, + unit, + Tezlink_protocols.Shell_impl.version * Block_services.block_info ) + Tezos_rpc.Service.t = + import_service Block_services.S.info end let chain_directory_path = Tezos_shell_services.Chain_services.path @@ -534,8 +569,8 @@ let register_block_services ~l2_chain_id ~impl:(fun {chain; block} () () -> let*? chain = check_chain chain in let*? block = check_block block in - let* header = Backend.header chain block in - Lwt_result_syntax.return (header, chain)) + let* tezlink_block = Backend.block chain block in + Lwt_result_syntax.return (tezlink_block, chain)) ~convert_output: (Protocol_types.Block_header.tezlink_block_to_block_header ~l2_chain_id) @@ -558,6 +593,17 @@ let register_block_services ~l2_chain_id _chain_id, _operation_inclusion_latency ) -> return (operation.protocol_data, Mock.receipts)) + (* TODO: https://gitlab.com/tezos/tezos/-/issues/7993 *) + (* RPCs at directory level doesn't appear properly in the describe RPC *) + |> register_with_conversion + ~service:Imported_services.block_info + ~impl:(fun {block; chain} q () -> + let*? chain = check_chain chain in + let*? block = check_block block in + let* tezlink_block = Backend.block chain block in + Lwt_result_syntax.return (q#version, tezlink_block, chain)) + ~convert_output: + (Protocol_types.Block.tezlink_block_to_block_info ~l2_chain_id) in Tezos_rpc.Directory.prefix block_directory_path diff --git a/etherlink/bin_node/lib_dev/tezlink_services_impl.ml b/etherlink/bin_node/lib_dev/tezlink_services_impl.ml index d103d355b3659963ec46654b88c426bb39fc04db..f1abaf1fbd4948f8a42264eb14688d062fa80f35 100644 --- a/etherlink/bin_node/lib_dev/tezlink_services_impl.ml +++ b/etherlink/bin_node/lib_dev/tezlink_services_impl.ml @@ -112,7 +112,7 @@ module Make (Backend : Backend) (Block_storage : Tezlink_block_storage_sig.S) : let `Main = chain in Tezlink_durable_storage.counter (read ~block) c - let header chain block = + let block chain block = let open Lwt_result_syntax in let `Main = chain in let* block_number = shell_block_param_to_block_number block in diff --git a/etherlink/tezt/lib/test_helpers.ml b/etherlink/tezt/lib/test_helpers.ml index 8daacb3f73d13833579a3313fcdf3e2071ba65b5..40e3ae1f24a61b272f85ea6c2d286ef40cd13da5 100644 --- a/etherlink/tezt/lib/test_helpers.ml +++ b/etherlink/tezt/lib/test_helpers.ml @@ -152,6 +152,35 @@ let check_header ~previous_header ~current_header ~chain_id ~current_timestamp = "Expected the timestamp of the current_block to be %R, but got %L" | _ -> () +(* Block info contains a raw header that differs slightly from the header returned by + the header RPC. + We need to append the hash and chain_id fields to our raw_header so that the function + check_header doesn't fail. *) +let block_info_to_header block_info = + let raw_header = JSON.(block_info |-> "header") in + let hash_raw_header = JSON.(put ("hash", block_info |-> "hash") raw_header) in + let header = + JSON.(put ("chain_id", block_info |-> "chain_id") hash_raw_header) + in + header + +let check_block_info ~previous_block_info ~current_block_info ~chain_id + ~current_timestamp = + let () = + check_header + ~previous_header:(block_info_to_header previous_block_info) + ~current_header:(block_info_to_header current_block_info) + ~chain_id + ~current_timestamp + in + (* For now operations are converted to dummy string as the list should be empty. + We convert to string operations to use the Check module *) + let operations = + JSON.(current_block_info |-> "operations" |> as_list |> List.map as_string) + in + Check.((operations = []) (list string)) + ~error_msg:"List of operations is expected to be empty for now" + let next_evm_level ~evm_node ~sc_rollup_node ~client = match Evm_node.mode evm_node with | Proxy -> diff --git a/etherlink/tezt/lib/test_helpers.mli b/etherlink/tezt/lib/test_helpers.mli index 76d41ec1eccaf2fdab02797957aa9712688e2c2e..6a5330deb163a65fb92af98421ded6d9d9ade7c3 100644 --- a/etherlink/tezt/lib/test_helpers.mli +++ b/etherlink/tezt/lib/test_helpers.mli @@ -87,6 +87,15 @@ val check_header : current_timestamp:string option -> unit +(** [check_block_info ~previous_block_info ~current_block_info] checks that two + consecutive block's info are consistent. *) +val check_block_info : + previous_block_info:JSON.t -> + current_block_info:JSON.t -> + chain_id:int option -> + current_timestamp:string option -> + unit + (** [next_evm_level ~evm_node ~sc_rollup_node ~client] moves [evm_node] to the next L2 level. *) val next_evm_level : diff --git a/etherlink/tezt/tests/evm_sequencer.ml b/etherlink/tezt/tests/evm_sequencer.ml index 4a3cd0de94d5975d4f027798e76a1217b1c71bbb..0cb9c92f732471e4369acab7f6243674647f9eb6 100644 --- a/etherlink/tezt/tests/evm_sequencer.ml +++ b/etherlink/tezt/tests/evm_sequencer.ml @@ -767,7 +767,7 @@ let test_tezlink_header = let endpoint = Client.( Foreign_endpoint - {(Evm_node.rpc_endpoint_record sequencer) with path = "tezlink"}) + {(Evm_node.rpc_endpoint_record sequencer) with path = "/tezlink"}) in let*@ n = Rpc.produce_block sequencer in @@ -793,6 +793,46 @@ let test_tezlink_header = ~chain_id ~current_timestamp:(Some current_timestamp) +let test_tezlink_block_info = + register_tezlink_test + ~title:"Test of the block_info rpc" + ~tags:["rpc"; "block_info"] + @@ fun {sequencer; client; l2_chains; _} _protocol -> + let chain_id = + match l2_chains with + | [l2_chain] -> Some l2_chain.l2_chain_id + | _ -> Test.fail ~__LOC__ "Expected one l2 chain" + in + + let endpoint = + Client.( + Foreign_endpoint + {(Evm_node.rpc_endpoint_record sequencer) with path = "/tezlink"}) + in + + let*@ n = Rpc.produce_block sequencer in + let* () = Evm_node.wait_for_blueprint_applied sequencer n in + let current_timestamp = + Tezos_base.Time.( + System.now () |> System.to_protocol |> Protocol.to_notation) + in + let*@ n = Rpc.produce_block ~timestamp:current_timestamp sequencer in + let* () = Evm_node.wait_for_blueprint_applied sequencer n in + let* block_1 = + Client.RPC.call ~hooks ~endpoint client + @@ RPC.get_chain_block ~block:"head~1" () + in + let* block_2 = + Client.RPC.call ~hooks ~endpoint client @@ RPC.get_chain_block () + in + + return + @@ check_block_info + ~previous_block_info:block_1 + ~current_block_info:block_2 + ~chain_id + ~current_timestamp:(Some current_timestamp) + let test_tezlink_bootstrapped = register_tezlink_test ~title:"Test of the bootstrapped rpc" @@ -841,7 +881,7 @@ let test_tezlink_monitor_heads = let open Lwt.Syntax in (* Prepare the RPC endpoint *) let rpc_info = Evm_node.rpc_endpoint_record sequencer in - let endpoint = Client.Foreign_endpoint {rpc_info with path = "tezlink"} in + let endpoint = Client.Foreign_endpoint {rpc_info with path = "/tezlink"} in let total_headers = 4 in @@ -13777,4 +13817,5 @@ let () = test_tezlink_chain_id [Alpha] ; test_tezlink_bootstrapped [Alpha] ; test_fa_deposit_can_be_claimed [Alpha] ; - test_eip2930_storage_access [Alpha] + test_eip2930_storage_access [Alpha] ; + test_tezlink_block_info [Alpha]