Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into add_open_api_spex_bea…
Browse files Browse the repository at this point in the history
…con_endpoints
  • Loading branch information
f3r10 committed Jan 20, 2024
2 parents 6ef27a7 + b1b0c78 commit 5fd4f1c
Show file tree
Hide file tree
Showing 20 changed files with 348 additions and 130 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,7 @@ fmt:
cd native/snappy_nif; cargo fmt
cd native/ssz_nif; cargo fmt
cd native/bls_nif; cargo fmt

#✅ dialyzer: @ Run dialyzer (static analysis tool).
dialyzer:
mix dialyzer
2 changes: 1 addition & 1 deletion config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ 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)
mock_execution = Keyword.get(args, :mock_execution, config_env() == :test)

config :lambda_ethereum_consensus, LambdaEthereumConsensus.ForkChoice,
checkpoint_sync: checkpoint_sync
Expand Down
35 changes: 35 additions & 0 deletions lib/chain_spec/configs/gen_config.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
defmodule ChainSpec.GenConfig do
@moduledoc """
Generic config behaviour, for auto-implementing configs.
"""

defmacro __using__(opts) do
file = Keyword.fetch!(opts, :file)
config = ConfigUtils.load_config_from_file!(file)
preset = Map.fetch!(config, "PRESET_BASE") |> parse_preset()

quote do
file = unquote(file)
config = unquote(Macro.escape(config))
preset = unquote(preset)

@external_resource file
@__parsed_config config
@__unified Map.merge(preset.get_preset(), @__parsed_config)

@behaviour unquote(__MODULE__)

@impl unquote(__MODULE__)
def get(key), do: Map.fetch!(@__unified, key)
end
end

defp parse_preset("mainnet"), do: MainnetPreset
defp parse_preset("minimal"), do: MinimalPreset
defp parse_preset(other), do: raise("Unknown preset: #{other}")

@doc """
Fetches a value from config.
"""
@callback get(String.t()) :: term()
end
9 changes: 1 addition & 8 deletions lib/chain_spec/configs/mainnet.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,5 @@ defmodule MainnetConfig do
@moduledoc """
Mainnet config constants.
"""
file = "config/networks/mainnet/config.yaml"

@external_resource file

@parsed_config ConfigUtils.load_config_from_file!(file)
@unified Map.merge(MainnetPreset.get_preset(), @parsed_config)

def get(key), do: Map.fetch!(@unified, key)
use ChainSpec.GenConfig, file: "config/networks/mainnet/config.yaml"
end
9 changes: 1 addition & 8 deletions lib/chain_spec/configs/minimal.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,5 @@ defmodule MinimalConfig do
@moduledoc """
Minimal config constants.
"""
file = "config/networks/minimal/config.yaml"

@external_resource file

@parsed_config ConfigUtils.load_config_from_file!(file)
@unified Map.merge(MinimalPreset.get_preset(), @parsed_config)

def get(key), do: Map.fetch!(@unified, key)
use ChainSpec.GenConfig, file: "config/networks/minimal/config.yaml"
end
9 changes: 1 addition & 8 deletions lib/chain_spec/configs/sepolia.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,5 @@ defmodule SepoliaConfig do
@moduledoc """
Sepolia config constants.
"""
file = "config/networks/sepolia/config.yaml"

@external_resource file

@parsed_config ConfigUtils.load_config_from_file!(file)
@unified Map.merge(MainnetPreset.get_preset(), @parsed_config)

def get(key), do: Map.fetch!(@unified, key)
use ChainSpec.GenConfig, file: "config/networks/sepolia/config.yaml"
end
27 changes: 27 additions & 0 deletions lib/chain_spec/presets/gen_preset.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule ChainSpec.GenPreset do
@moduledoc """
Generic preset behaviour, for auto-implementing presets.
"""

defmacro __using__(opts) do
file = Keyword.fetch!(opts, :file)

quote do
file = unquote(file)

@external_resource file

@__parsed_preset ConfigUtils.load_preset_from_dir!(file)

@behaviour unquote(__MODULE__)

@impl unquote(__MODULE__)
def get_preset, do: @__parsed_preset
end
end

@doc """
Fetches the whole preset.
"""
@callback get_preset() :: map()
end
8 changes: 1 addition & 7 deletions lib/chain_spec/presets/mainnet.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,5 @@ defmodule MainnetPreset do
@moduledoc """
Mainnet preset constants.
"""

file = "config/presets/mainnet"
@external_resource file

@parsed_preset ConfigUtils.load_preset_from_dir!(file)

def get_preset, do: @parsed_preset
use ChainSpec.GenPreset, file: "config/presets/mainnet"
end
8 changes: 1 addition & 7 deletions lib/chain_spec/presets/minimal.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,5 @@ defmodule MinimalPreset do
@moduledoc """
Minimal preset constants.
"""

file = "config/presets/minimal"
@external_resource file

@parsed_preset ConfigUtils.load_preset_from_dir!(file)

def get_preset, do: @parsed_preset
use ChainSpec.GenPreset, file: "config/presets/minimal"
end
99 changes: 74 additions & 25 deletions lib/lambda_ethereum_consensus/beacon/beacon_chain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,20 @@ defmodule LambdaEthereumConsensus.Beacon.BeaconChain do
defstruct [
:genesis_time,
:genesis_validators_root,
:time
:time,
:cached_fork_choice
]

@type t :: %__MODULE__{
genesis_time: Types.uint64(),
genesis_validators_root: Types.bytes32(),
time: Types.uint64()
time: Types.uint64(),
cached_fork_choice: %{
head_root: Types.root(),
head_slot: Types.slot(),
finalized_root: Types.root(),
finalized_epoch: Types.epoch()
}
}
end

Expand All @@ -33,6 +40,14 @@ defmodule LambdaEthereumConsensus.Beacon.BeaconChain do
GenServer.call(__MODULE__, :get_current_slot)
end

@spec update_fork_choice_cache(Types.root(), Types.slot(), Types.root(), Types.epoch()) :: :ok
def update_fork_choice_cache(head_root, head_slot, finalized_root, finalized_epoch) do
GenServer.cast(
__MODULE__,
{:update_fork_choice_cache, head_root, head_slot, finalized_root, finalized_epoch}
)
end

@spec get_current_epoch() :: integer()
def get_current_epoch do
Misc.compute_epoch_at_slot(get_current_slot())
Expand All @@ -50,20 +65,8 @@ defmodule LambdaEthereumConsensus.Beacon.BeaconChain do

@spec get_current_status_message() :: {:ok, Types.StatusMessage.t()} | {:error, any}
def get_current_status_message do
# TODO: un-hardcode when get_head is optimized and/or cached
# GenServer.call(__MODULE__, :get_current_status_message, @default_timeout)

# hardcoded response from random peer
{:ok,
%Types.StatusMessage{
fork_digest: get_fork_digest(),
finalized_root:
Base.decode16!("7715794499C07D9954DD223EC2C6B846D3BAB27956D093000FADC1B8219F74D4"),
finalized_epoch: 228_168,
head_root:
Base.decode16!("D62A74AE0F933224133C5E6E1827A2835A1E705F0CDFEE3AD25808DDEA5572DB"),
head_slot: 7_301_450
}}
status_message = GenServer.call(__MODULE__, :get_current_status_message)
{:ok, status_message}
end

##########################
Expand All @@ -79,6 +82,12 @@ defmodule LambdaEthereumConsensus.Beacon.BeaconChain do
%BeaconChainState{
genesis_time: anchor_state.genesis_time,
genesis_validators_root: anchor_state.genesis_validators_root,
cached_fork_choice: %{
head_root: <<0::256>>,
head_slot: anchor_state.slot,
finalized_root: anchor_state.finalized_checkpoint.root,
finalized_epoch: anchor_state.finalized_checkpoint.epoch
},
time: time
}}
end
Expand All @@ -90,23 +99,38 @@ defmodule LambdaEthereumConsensus.Beacon.BeaconChain do

@impl true
def handle_call({:get_fork_digest, slot}, _from, state) do
current_fork_version =
fork_digest =
case slot do
nil -> compute_current_slot(state)
_ -> slot
end
|> Misc.compute_epoch_at_slot()
|> ChainSpec.get_fork_version_for_epoch()

fork_digest =
Misc.compute_fork_digest(
current_fork_version,
state.genesis_validators_root
)
|> compute_fork_digest(state.genesis_validators_root)

{:reply, fork_digest, state}
end

@impl true
@spec handle_call(:get_current_status_message, any, BeaconChainState.t()) ::
{:reply, Types.StatusMessage.t(), BeaconChainState.t()}
def handle_call(:get_current_status_message, _from, state) do
%{
head_root: head_root,
head_slot: head_slot,
finalized_root: finalized_root,
finalized_epoch: finalized_epoch
} = state.cached_fork_choice

status_message = %Types.StatusMessage{
fork_digest: compute_fork_digest(head_slot, state.genesis_validators_root),
finalized_root: finalized_root,
finalized_epoch: finalized_epoch,
head_root: head_root,
head_slot: head_slot
}

{:reply, status_message, state}
end

@impl true
def handle_info(:on_tick, state) do
schedule_next_tick()
Expand All @@ -118,6 +142,21 @@ defmodule LambdaEthereumConsensus.Beacon.BeaconChain do
{:noreply, %BeaconChainState{state | time: time}}
end

@impl true
def handle_cast(
{:update_fork_choice_cache, head_root, head_slot, finalized_root, finalized_epoch},
state
) do
{:noreply,
state
|> Map.put(:cached_fork_choice, %{
head_root: head_root,
head_slot: head_slot,
finalized_root: finalized_root,
finalized_epoch: finalized_epoch
})}
end

def schedule_next_tick do
# For millisecond precision
time_to_next_tick = 1000 - rem(:os.system_time(:millisecond), 1000)
Expand All @@ -127,4 +166,14 @@ defmodule LambdaEthereumConsensus.Beacon.BeaconChain do
defp compute_current_slot(state) do
div(state.time - state.genesis_time, ChainSpec.get("SECONDS_PER_SLOT"))
end

defp compute_fork_digest(slot, genesis_validators_root) do
current_fork_version =
slot |> Misc.compute_epoch_at_slot() |> ChainSpec.get_fork_version_for_epoch()

Misc.compute_fork_digest(
current_fork_version,
genesis_validators_root
)
end
end
19 changes: 10 additions & 9 deletions lib/lambda_ethereum_consensus/execution/engine_api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,20 @@ defmodule LambdaEthereumConsensus.Execution.EngineApi do
@spec exchange_capabilities() :: {:ok, any} | {:error, any}
def exchange_capabilities, do: impl().exchange_capabilities()

@spec new_payload_v1(Types.ExecutionPayload.t()) ::
@spec new_payload(Types.ExecutionPayload.t()) ::
{:ok, any} | {:error, any}
def new_payload_v1(execution_payload), do: impl().new_payload_v1(execution_payload)
def new_payload(execution_payload), do: impl().new_payload(execution_payload)

@spec forkchoice_updated(map, map | any) :: {:ok, any} | {:error, any}
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
)
defp impl do
Application.fetch_env!(
:lambda_ethereum_consensus,
__MODULE__
)[
:implementation
]
end
end
17 changes: 7 additions & 10 deletions lib/lambda_ethereum_consensus/execution/engine_api/api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,18 @@ defmodule LambdaEthereumConsensus.Execution.EngineApi.Api do
call("engine_exchangeCapabilities", [@supported_methods])
end

@spec new_payload_v1(Types.ExecutionPayload.t()) ::
@spec new_payload(Types.ExecutionPayload.t()) ::
{:ok, any} | {:error, any}
def new_payload_v1(execution_payload) do
call("engine_newPayloadV2", [execution_payload])
def new_payload(execution_payload) do
call("engine_newPayloadV2", [RPC.normalize(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])
call("engine_forkchoiceUpdatedV2", [
RPC.normalize(forkchoice_state),
RPC.normalize(payload_attributes)
])
end

defp call(method, params) do
Expand Down
Loading

0 comments on commit 5fd4f1c

Please sign in to comment.