From fa95fa5ea27289199cd57616f07745565ec42cb0 Mon Sep 17 00:00:00 2001 From: Pierrick Couderc Date: Mon, 20 May 2024 12:25:00 +0200 Subject: [PATCH 1/3] EVM/Node: read general trace result Co-authored-by: Rodi-Can Bozman Apply 1 suggestion(s) to 1 file(s) Co-authored-by: Rodi-Can Bozman --- .../bin_node/lib_dev/durable_storage_path.ml | 10 ++++- .../bin_node/lib_dev/durable_storage_path.mli | 9 ++++ .../lib_dev/encodings/tracer_types.ml | 41 +++++++++++++++++++ .../lib_dev/encodings/tracer_types.mli | 15 +++++++ .../bin_node/lib_dev/services_backend_sig.ml | 4 +- etherlink/bin_node/lib_dev/tracer.ml | 22 +++++++++- etherlink/bin_node/lib_dev/tracer.mli | 2 +- etherlink/bin_node/lib_dev/tracer_sig.ml | 2 +- 8 files changed, 100 insertions(+), 5 deletions(-) diff --git a/etherlink/bin_node/lib_dev/durable_storage_path.ml b/etherlink/bin_node/lib_dev/durable_storage_path.ml index 5666b2e3d035..c2e80401f3b0 100644 --- a/etherlink/bin_node/lib_dev/durable_storage_path.ml +++ b/etherlink/bin_node/lib_dev/durable_storage_path.ml @@ -117,5 +117,13 @@ module Evm_events = struct end module Trace_transaction = struct - let input = EVM.make "/trace/input" + let root = EVM.make "/trace" + + let input = root ^ "/input" + + let output_gas = root ^ "/gas" + + let output_failed = root ^ "/failed" + + let output_return_value = root ^ "/return_value" end diff --git a/etherlink/bin_node/lib_dev/durable_storage_path.mli b/etherlink/bin_node/lib_dev/durable_storage_path.mli index 0bf93a8353e6..66eb5f15e09c 100644 --- a/etherlink/bin_node/lib_dev/durable_storage_path.mli +++ b/etherlink/bin_node/lib_dev/durable_storage_path.mli @@ -95,4 +95,13 @@ end module Trace_transaction : sig (** Path where is stored the input of the tracer. *) val input : path + + (** Path where is stored the gas consumed by the call. *) + val output_gas : path + + (** Path where the result of the traced transaction is stored. *) + val output_failed : path + + (** Path where is stored the value returned by the transaction's execution. *) + val output_return_value : path end diff --git a/etherlink/bin_node/lib_dev/encodings/tracer_types.ml b/etherlink/bin_node/lib_dev/encodings/tracer_types.ml index 29d82b3963b7..bfdf9dfb79df 100644 --- a/etherlink/bin_node/lib_dev/encodings/tracer_types.ml +++ b/etherlink/bin_node/lib_dev/encodings/tracer_types.ml @@ -114,3 +114,44 @@ let input_rlp_encoder hash config = let stack = bool_encoding config.tracer_config.disable_stack in let storage = bool_encoding config.tracer_config.disable_storage in List [hash; return_data; memory; stack; storage] |> encode |> Bytes.to_string + +(* This is a temporary type, it should be filled in a follow up patch. Int and + not unit, so that the encoding doesn't fail with: "Cannot insert potentially + zero-sized element in a list." Making it a list ensures it is encoded as an + (empty) array and compatible with the specification until the correct + type. *) +type opcode_log = int + +type output = { + gas : int64; + failed : bool; + return_value : Ethereum_types.hash; + struct_logs : opcode_log list; +} + +let output_encoding = + let open Data_encoding in + conv + (fun {gas; failed; return_value; struct_logs} -> + (gas, failed, return_value, struct_logs)) + (fun (gas, failed, return_value, struct_logs) -> + {gas; failed; return_value; struct_logs}) + (obj4 + (req "gas" int64) + (req "failed" bool) + (req "returnValue" Ethereum_types.hash_encoding) + (req "structLogs" (list int31))) + +let output_binary_decoder ~gas ~failed ~return_value = + let gas = + Ethereum_types.decode_number gas |> fun (Ethereum_types.Qty z) -> + Z.to_int64 z + in + let failed = + if Bytes.length failed = 0 then false else Bytes.get failed 0 = '\x01' + in + let return_value = + let (`Hex hex_value) = Hex.of_bytes return_value in + Ethereum_types.hash_of_string hex_value + in + {gas; failed; return_value; struct_logs = []} diff --git a/etherlink/bin_node/lib_dev/encodings/tracer_types.mli b/etherlink/bin_node/lib_dev/encodings/tracer_types.mli index 920280e1582d..a27f1a767b08 100644 --- a/etherlink/bin_node/lib_dev/encodings/tracer_types.mli +++ b/etherlink/bin_node/lib_dev/encodings/tracer_types.mli @@ -42,3 +42,18 @@ type input = Ethereum_types.hash * config val input_encoding : (Ethereum_types.hash * config) Data_encoding.t val input_rlp_encoder : Ethereum_types.hash -> config -> string + +(* This is a temporary type, it should be filled in a follow up patch. *) +type opcode_log + +type output = { + gas : int64; + failed : bool; + return_value : Ethereum_types.hash; + struct_logs : opcode_log list; +} + +val output_encoding : output Data_encoding.t + +val output_binary_decoder : + gas:bytes -> failed:bytes -> return_value:bytes -> output diff --git a/etherlink/bin_node/lib_dev/services_backend_sig.ml b/etherlink/bin_node/lib_dev/services_backend_sig.ml index 845ae5ccfb12..a5a02184ad32 100644 --- a/etherlink/bin_node/lib_dev/services_backend_sig.ml +++ b/etherlink/bin_node/lib_dev/services_backend_sig.ml @@ -139,7 +139,9 @@ module type S = sig transaction [hash], and traces this transaction with the specified [tracer]. *) val trace_transaction : - Ethereum_types.hash -> Tracer_types.config -> unit tzresult Lwt.t + Ethereum_types.hash -> + Tracer_types.config -> + Tracer_types.output tzresult Lwt.t end module type Backend = sig diff --git a/etherlink/bin_node/lib_dev/tracer.ml b/etherlink/bin_node/lib_dev/tracer.ml index bd0266a613c0..cc864b4be9f7 100644 --- a/etherlink/bin_node/lib_dev/tracer.ml +++ b/etherlink/bin_node/lib_dev/tracer.ml @@ -5,6 +5,26 @@ (* *) (*****************************************************************************) +let read_value state path = + let open Lwt_result_syntax in + let*! value = Evm_state.inspect state path in + match value with + | None -> tzfail Tracer_types.Trace_not_found + | Some value -> return value + +let read_output state = + let open Lwt_result_syntax in + let* gas = + read_value state Durable_storage_path.Trace_transaction.output_gas + in + let* failed = + read_value state Durable_storage_path.Trace_transaction.output_failed + in + let* return_value = + read_value state Durable_storage_path.Trace_transaction.output_return_value + in + return @@ Tracer_types.output_binary_decoder ~gas ~failed ~return_value + let trace_transaction ~block_number ~transaction_hash ~config = let open Lwt_result_syntax in let input = Tracer_types.input_rlp_encoder transaction_hash config in @@ -25,4 +45,4 @@ let trace_transaction ~block_number ~transaction_hash ~config = in match apply_result with | Apply_failure -> tzfail Tracer_types.Trace_not_found - | Apply_success _ -> return_unit + | Apply_success {evm_state; _} -> read_output evm_state diff --git a/etherlink/bin_node/lib_dev/tracer.mli b/etherlink/bin_node/lib_dev/tracer.mli index f93f06510aeb..f61af2c0794d 100644 --- a/etherlink/bin_node/lib_dev/tracer.mli +++ b/etherlink/bin_node/lib_dev/tracer.mli @@ -12,4 +12,4 @@ val trace_transaction : block_number:Ethereum_types.quantity -> transaction_hash:Ethereum_types.hash -> config:Tracer_types.config -> - unit tzresult Lwt.t + Tracer_types.output tzresult Lwt.t diff --git a/etherlink/bin_node/lib_dev/tracer_sig.ml b/etherlink/bin_node/lib_dev/tracer_sig.ml index e49edd87bd09..a937bd9a3e03 100644 --- a/etherlink/bin_node/lib_dev/tracer_sig.ml +++ b/etherlink/bin_node/lib_dev/tracer_sig.ml @@ -10,7 +10,7 @@ module type Backend = sig block_number:Ethereum_types.quantity -> transaction_hash:Ethereum_types.hash -> config:Tracer_types.config -> - unit tzresult Lwt.t + Tracer_types.output tzresult Lwt.t end module Make (Storage : sig -- GitLab From bac1af51c0fd26fed5fe3dc8f34d1355c6e3a6e5 Mon Sep 17 00:00:00 2001 From: Pierrick Couderc Date: Wed, 22 May 2024 15:16:37 +0200 Subject: [PATCH 2/3] EVM/Node: default values for unavailable traced values --- etherlink/bin_node/lib_dev/tracer.ml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/etherlink/bin_node/lib_dev/tracer.ml b/etherlink/bin_node/lib_dev/tracer.ml index cc864b4be9f7..497731d00113 100644 --- a/etherlink/bin_node/lib_dev/tracer.ml +++ b/etherlink/bin_node/lib_dev/tracer.ml @@ -5,12 +5,15 @@ (* *) (*****************************************************************************) -let read_value state path = +let read_value ?default state path = let open Lwt_result_syntax in let*! value = Evm_state.inspect state path in match value with - | None -> tzfail Tracer_types.Trace_not_found | Some value -> return value + | None -> ( + match default with + | Some d -> return d + | None -> tzfail Tracer_types.Trace_not_found) let read_output state = let open Lwt_result_syntax in @@ -21,7 +24,11 @@ let read_output state = read_value state Durable_storage_path.Trace_transaction.output_failed in let* return_value = - read_value state Durable_storage_path.Trace_transaction.output_return_value + read_value + (* The key doesn't exist if there is no value returned by the transaction *) + ~default:Bytes.empty + state + Durable_storage_path.Trace_transaction.output_return_value in return @@ Tracer_types.output_binary_decoder ~gas ~failed ~return_value -- GitLab From 1eff14c19e6dea7b42e37f541c5dd084399741a9 Mon Sep 17 00:00:00 2001 From: Pierrick Couderc Date: Wed, 22 May 2024 15:51:36 +0200 Subject: [PATCH 3/3] EVM/Node: return the tracer output in the RPC --- etherlink/bin_node/lib_dev/rpc_encodings.ml | 4 ++-- etherlink/bin_node/lib_dev/rpc_encodings.mli | 4 +++- etherlink/bin_node/lib_dev/services.ml | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/etherlink/bin_node/lib_dev/rpc_encodings.ml b/etherlink/bin_node/lib_dev/rpc_encodings.ml index 6b2dcb09d183..196df4331993 100644 --- a/etherlink/bin_node/lib_dev/rpc_encodings.ml +++ b/etherlink/bin_node/lib_dev/rpc_encodings.ml @@ -709,11 +709,11 @@ end module Trace_transaction = struct type input = Tracer_types.input - type output = unit + type output = Tracer_types.output let input_encoding = Tracer_types.input_encoding - let output_encoding = Data_encoding.unit + let output_encoding = Tracer_types.output_encoding let method_ = "debug_traceTransaction" diff --git a/etherlink/bin_node/lib_dev/rpc_encodings.mli b/etherlink/bin_node/lib_dev/rpc_encodings.mli index 0605ec97933e..29cdf9bc263d 100644 --- a/etherlink/bin_node/lib_dev/rpc_encodings.mli +++ b/etherlink/bin_node/lib_dev/rpc_encodings.mli @@ -278,7 +278,9 @@ module Replay_block : and type output = Ethereum_types.block module Trace_transaction : - METHOD with type input = Tracer_types.input and type output = unit + METHOD + with type input = Tracer_types.input + and type output = Tracer_types.output type map_result = | Method : diff --git a/etherlink/bin_node/lib_dev/services.ml b/etherlink/bin_node/lib_dev/services.ml index dc26baac3082..b9efe69ab16b 100644 --- a/etherlink/bin_node/lib_dev/services.ml +++ b/etherlink/bin_node/lib_dev/services.ml @@ -409,7 +409,7 @@ let dispatch_request (config : Configuration.t) let f ((hash, config) : Tracer_types.input) = let*! trace = Backend_rpc.trace_transaction hash config in match trace with - | Ok _ -> rpc_ok () + | Ok trace -> rpc_ok trace | Error (Tracer_types.Not_supported :: _) -> rpc_error (Rpc_errors.method_not_supported Trace_transaction.method_) -- GitLab