Skip to content

Commit

Permalink
feat: mock execution client (lambdaclass#616)
Browse files Browse the repository at this point in the history
  • Loading branch information
karasakalmt authored Jan 15, 2024
1 parent 7b1f559 commit bad2717
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 33 deletions.
10 changes: 9 additions & 1 deletion config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ import Config
network: :string,
checkpoint_sync: :string,
execution_endpoint: :string,
execution_jwt: :string
execution_jwt: :string,
mock_execution: :boolean
]
)

network = Keyword.get(args, :network, "mainnet")
checkpoint_sync = Keyword.get(args, :checkpoint_sync)
execution_endpoint = Keyword.get(args, :execution_endpoint, "http://localhost:8551")
jwt_path = Keyword.get(args, :execution_jwt)
mock_execution = Keyword.get(args, :mock_execution, false)

config :lambda_ethereum_consensus, LambdaEthereumConsensus.ForkChoice,
checkpoint_sync: checkpoint_sync
Expand All @@ -38,9 +40,15 @@ jwt_secret =
nil
end

implementation =
if mock_execution,
do: LambdaEthereumConsensus.Execution.EngineApi.Mocked,
else: LambdaEthereumConsensus.Execution.EngineApi.Api

config :lambda_ethereum_consensus, LambdaEthereumConsensus.Execution.EngineApi,
endpoint: execution_endpoint,
jwt_secret: jwt_secret,
implementation: implementation,
version: "2.0"

# Configures metrics
Expand Down
45 changes: 13 additions & 32 deletions lib/lambda_ethereum_consensus/execution/engine_api.ex
Original file line number Diff line number Diff line change
@@ -1,47 +1,28 @@
defmodule LambdaEthereumConsensus.Execution.EngineApi do
@moduledoc """
Execution Layer Engine API methods
Execution Layer Engine API methods with routing
"""

alias LambdaEthereumConsensus.Execution.Auth
alias LambdaEthereumConsensus.Execution.RPC

@supported_methods ["engine_newPayloadV2"]

@doc """
Using this method Execution and consensus layer client software may
exchange with a list of supported Engine API methods.
"""
@spec exchange_capabilities() :: {:ok, any} | {:error, any}
def exchange_capabilities do
call("engine_exchangeCapabilities", [@supported_methods])
end
def exchange_capabilities, do: impl().exchange_capabilities()

@spec new_payload_v1(Types.ExecutionPayload.t()) ::
{:ok, any} | {:error, any}
def new_payload_v1(execution_payload) do
call("engine_newPayloadV2", [execution_payload])
end
def new_payload_v1(execution_payload), do: impl().new_payload_v1(execution_payload)

@spec forkchoice_updated(map, map | any) :: {:ok, any} | {:error, any}
def forkchoice_updated(forkchoice_state, payload_attributes) do
forkchoice_state =
forkchoice_state
|> Map.update!("finalizedBlockHash", &RPC.encode_binary/1)
|> Map.update!("headBlockHash", &RPC.encode_binary/1)
|> Map.update!("safeBlockHash", &RPC.encode_binary/1)

call("engine_forkchoiceUpdatedV2", [forkchoice_state, payload_attributes])
end

defp call(method, params) do
config = Application.fetch_env!(:lambda_ethereum_consensus, __MODULE__)

endpoint = Keyword.fetch!(config, :endpoint)
version = Keyword.fetch!(config, :version)
jwt_secret = Keyword.fetch!(config, :jwt_secret)

{:ok, jwt, _} = Auth.generate_token(jwt_secret)
RPC.rpc_call(endpoint, jwt, version, method, params)
end
def forkchoice_updated(forkchoice_state, payload_attributes),
do: impl().forkchoice_updated(forkchoice_state, payload_attributes)

defp impl,
do:
Application.get_env(
__MODULE__,
:implementation,
LambdaEthereumConsensus.Execution.EngineApi.Api
)
end
51 changes: 51 additions & 0 deletions lib/lambda_ethereum_consensus/execution/engine_api/api.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
defmodule LambdaEthereumConsensus.Execution.EngineApi.Api do
@moduledoc """
Execution Layer Engine API methods
"""

alias LambdaEthereumConsensus.Execution.Auth
alias LambdaEthereumConsensus.Execution.RPC

@supported_methods ["engine_newPayloadV2"]

@doc """
Using this method Execution and consensus layer client software may
exchange with a list of supported Engine API methods.
"""
@spec exchange_capabilities() :: {:ok, any} | {:error, any}
def exchange_capabilities do
call("engine_exchangeCapabilities", [@supported_methods])
end

@spec new_payload_v1(Types.ExecutionPayload.t()) ::
{:ok, any} | {:error, any}
def new_payload_v1(execution_payload) do
call("engine_newPayloadV2", [execution_payload])
end

@spec forkchoice_updated(map, map | any) :: {:ok, any} | {:error, any}
def forkchoice_updated(forkchoice_state, payload_attributes) do
forkchoice_state =
forkchoice_state
|> Map.update!("finalizedBlockHash", &RPC.encode_binary/1)
|> Map.update!("headBlockHash", &RPC.encode_binary/1)
|> Map.update!("safeBlockHash", &RPC.encode_binary/1)

call("engine_forkchoiceUpdatedV2", [forkchoice_state, payload_attributes])
end

defp call(method, params) do
config =
Application.fetch_env!(
:lambda_ethereum_consensus,
LambdaEthereumConsensus.Execution.EngineApi
)

endpoint = Keyword.fetch!(config, :endpoint)
version = Keyword.fetch!(config, :version)
jwt_secret = Keyword.fetch!(config, :jwt_secret)

{:ok, jwt, _} = Auth.generate_token(jwt_secret)
RPC.rpc_call(endpoint, jwt, version, method, params)
end
end
53 changes: 53 additions & 0 deletions lib/lambda_ethereum_consensus/execution/engine_api/mocked.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
defmodule LambdaEthereumConsensus.Execution.EngineApi.Mocked do
@moduledoc """
Mock Execution Layer Engine API methods
"""

@doc """
Using this method Execution and consensus layer client software may
exchange with a list of supported Engine API methods.
"""
@spec exchange_capabilities() :: {:ok, any} | {:error, any}
def exchange_capabilities do
{:ok, ["engine_newPayloadV2"]}
end

@spec new_payload_v1(Types.ExecutionPayload.t()) ::
{:ok, any} | {:error, any}
def new_payload_v1(_execution_payload) do
{:ok, generic_response()}
end

@spec forkchoice_updated(map, map | any) :: {:ok, any} | {:error, any}
def forkchoice_updated(_forkchoice_state, _payload_attributes) do
{:ok, generic_response()}
end

defp generic_response do
%{
id: 1,
jsonrpc: "2.0",
result: %{
payloadId: nil,
payloadStatus: %{
status: "VALID",
latestValidHash: nil,
validationError: nil
}
},
error: ""
}
end

# # This will be used for logging
# defp mock_call(method, params) do
# config =
# Application.fetch_env!(
# :lambda_ethereum_consensus,
# LambdaEthereumConsensus.Execution.EngineApi
# )

# endpoint = Keyword.fetch!(config, :endpoint)
# version = Keyword.fetch!(config, :version)
# end
end

0 comments on commit bad2717

Please sign in to comment.