Skip to content

Commit 3c58d61

Browse files
authored
refactor: cleanup fork tree utilities. (#1035)
1 parent 7a7b5a9 commit 3c58d61

File tree

10 files changed

+352
-558
lines changed

10 files changed

+352
-558
lines changed

lib/beacon_api/controllers/v1/beacon_controller.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ defmodule BeaconApi.V1.BeaconController do
33

44
alias BeaconApi.ApiSpec
55
alias BeaconApi.ErrorController
6+
alias BeaconApi.Helpers
67
alias BeaconApi.Utils
78
alias LambdaEthereumConsensus.Beacon.BeaconChain
8-
alias LambdaEthereumConsensus.ForkChoice
99
alias LambdaEthereumConsensus.Store.BlockDb
1010
alias LambdaEthereumConsensus.Store.Blocks
1111

@@ -40,7 +40,7 @@ defmodule BeaconApi.V1.BeaconController do
4040

4141
@spec get_state_root(Plug.Conn.t(), any) :: Plug.Conn.t()
4242
def get_state_root(conn, %{state_id: state_id}) do
43-
case BeaconApi.Utils.parse_id(state_id) |> ForkChoice.Helpers.state_root_by_state_id() do
43+
case BeaconApi.Utils.parse_id(state_id) |> Helpers.state_root_by_state_id() do
4444
{:ok, {root, execution_optimistic, finalized}} ->
4545
conn |> root_response(root, execution_optimistic, finalized)
4646

@@ -107,7 +107,7 @@ defmodule BeaconApi.V1.BeaconController do
107107

108108
@spec get_finality_checkpoints(Plug.Conn.t(), any) :: Plug.Conn.t()
109109
def get_finality_checkpoints(conn, %{state_id: state_id}) do
110-
case BeaconApi.Utils.parse_id(state_id) |> ForkChoice.Helpers.finality_checkpoint_by_id() do
110+
case BeaconApi.Utils.parse_id(state_id) |> Helpers.finality_checkpoint_by_id() do
111111
{:ok,
112112
{previous_justified_checkpoint, current_justified_checkpoint, finalized_checkpoint,
113113
execution_optimistic, finalized}} ->

lib/beacon_api/helpers.ex

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
defmodule BeaconApi.Helpers do
2+
@moduledoc """
3+
Helper functions for the Beacon API
4+
"""
5+
6+
alias LambdaEthereumConsensus.Beacon.BeaconChain
7+
alias LambdaEthereumConsensus.Store.BlockDb
8+
alias LambdaEthereumConsensus.Store.Blocks
9+
alias LambdaEthereumConsensus.Store.StateDb
10+
11+
alias Types.BeaconState
12+
alias Types.SignedBeaconBlock
13+
14+
@type named_root() :: :genesis | :justified | :finalized | :head
15+
@type block_id() :: named_root() | :invalid_id | Types.slot() | Types.root()
16+
@type state_id() :: named_root() | :invalid_id | Types.slot() | Types.root()
17+
@type block_info() ::
18+
{SignedBeaconBlock.t(), execution_optimistic? :: boolean(), finalized? :: boolean()}
19+
@type state_info() ::
20+
{BeaconState.t(), execution_optimistic? :: boolean(), finalized? :: boolean()}
21+
@type root_info() ::
22+
{Types.root(), execution_optimistic? :: boolean(), finalized? :: boolean()}
23+
@type finality_info() ::
24+
{Types.Checkpoint.t(), Types.Checkpoint.t(), Types.Checkpoint.t(),
25+
execution_optimistic? :: boolean(), finalized? :: boolean()}
26+
27+
def root_by_id(:justified) do
28+
justified_checkpoint = BeaconChain.get_justified_checkpoint()
29+
# TODO compute is_optimistic_or_invalid
30+
execution_optimistic = true
31+
{:ok, {justified_checkpoint.root, execution_optimistic, false}}
32+
end
33+
34+
def root_by_id(:finalized) do
35+
finalized_checkpoint = BeaconChain.get_finalized_checkpoint()
36+
# TODO compute is_optimistic_or_invalid
37+
execution_optimistic = true
38+
{:ok, {finalized_checkpoint.root, execution_optimistic, true}}
39+
end
40+
41+
def root_by_id(hex_root) when is_binary(hex_root) do
42+
# TODO compute is_optimistic_or_invalid() and is_finalized()
43+
execution_optimistic = true
44+
finalized = false
45+
{:ok, {hex_root, execution_optimistic, finalized}}
46+
end
47+
48+
@spec block_root_by_block_id(block_id()) ::
49+
{:ok, root_info()} | {:error, String.t()} | :not_found | :empty_slot | :invalid_id
50+
def block_root_by_block_id(:head) do
51+
with {:ok, current_status} <- BeaconChain.get_current_status_message() do
52+
# TODO compute is_optimistic_or_invalid
53+
execution_optimistic = true
54+
{:ok, {current_status.head_root, execution_optimistic, false}}
55+
end
56+
end
57+
58+
def block_root_by_block_id(:genesis), do: :not_found
59+
60+
def block_root_by_block_id(:justified) do
61+
with justified_checkpoint <- BeaconChain.get_justified_checkpoint() do
62+
# TODO compute is_optimistic_or_invalid
63+
execution_optimistic = true
64+
{:ok, {justified_checkpoint.root, execution_optimistic, false}}
65+
end
66+
end
67+
68+
def block_root_by_block_id(:finalized) do
69+
with finalized_checkpoint <- BeaconChain.get_finalized_checkpoint() do
70+
# TODO compute is_optimistic_or_invalid
71+
execution_optimistic = true
72+
{:ok, {finalized_checkpoint.root, execution_optimistic, true}}
73+
end
74+
end
75+
76+
def block_root_by_block_id(:invalid_id), do: :invalid_id
77+
78+
def block_root_by_block_id(slot) when is_integer(slot) do
79+
with :ok <- check_valid_slot(slot, BeaconChain.get_current_slot()),
80+
{:ok, root} <- BlockDb.get_block_root_by_slot(slot) do
81+
# TODO compute is_optimistic_or_invalid() and is_finalized()
82+
execution_optimistic = true
83+
finalized = false
84+
{:ok, {root, execution_optimistic, finalized}}
85+
end
86+
end
87+
88+
@spec state_root_by_state_id(state_id()) ::
89+
{:ok, root_info()} | {:error, String.t()} | :not_found | :empty_slot | :invalid_id
90+
def state_root_by_state_id(hex_root) when is_binary(hex_root) do
91+
# TODO compute is_optimistic_or_invalid() and is_finalized()
92+
execution_optimistic = true
93+
finalized = false
94+
95+
case StateDb.get_state_by_state_root(hex_root) do
96+
{:ok, _state} -> {:ok, {hex_root, execution_optimistic, finalized}}
97+
_ -> :not_found
98+
end
99+
end
100+
101+
def state_root_by_state_id(id) do
102+
with {:ok, {block_root, optimistic, finalized}} <- block_root_by_block_id(id),
103+
{:ok, block} <- BlockDb.get_block(block_root) do
104+
%{message: %{state_root: state_root}} = block
105+
{:ok, {state_root, optimistic, finalized}}
106+
end
107+
end
108+
109+
@spec block_by_block_id(block_id()) ::
110+
{:ok, block_info()}
111+
| {:error, String.t()}
112+
| :not_found
113+
| :empty_slot
114+
| :invalid_id
115+
def block_by_block_id(block_id) do
116+
with {:ok, {root, optimistic, finalized}} <- block_root_by_block_id(block_id),
117+
{:ok, block} <- BlockDb.get_block(root) do
118+
{:ok, {block, optimistic, finalized}}
119+
end
120+
end
121+
122+
@spec state_by_state_id(state_id()) ::
123+
{:ok, state_info()}
124+
| {:error, String.t()}
125+
| :not_found
126+
| :empty_slot
127+
| :invalid_id
128+
def state_by_state_id(hex_root) when is_binary(hex_root) do
129+
# TODO compute is_optimistic_or_invalid() and is_finalized()
130+
execution_optimistic = true
131+
finalized = false
132+
133+
case StateDb.get_state_by_state_root(hex_root) do
134+
{:ok, state} -> {:ok, {state, execution_optimistic, finalized}}
135+
_ -> :not_found
136+
end
137+
end
138+
139+
def state_by_state_id(id) do
140+
with {:ok, {%{message: %{state_root: state_root}}, optimistic, finalized}} <-
141+
block_by_block_id(id),
142+
{:ok, state} <-
143+
StateDb.get_state_by_state_root(state_root) do
144+
{:ok, {state, optimistic, finalized}}
145+
end
146+
end
147+
148+
@spec finality_checkpoint_by_id(state_id()) ::
149+
{:ok, finality_info()} | {:error, String.t()} | :not_found | :empty_slot | :invalid_id
150+
def finality_checkpoint_by_id(id) do
151+
with {:ok, {state, optimistic, finalized}} <- state_by_state_id(id) do
152+
{:ok,
153+
{state.previous_justified_checkpoint, state.current_justified_checkpoint,
154+
state.finalized_checkpoint, optimistic, finalized}}
155+
end
156+
end
157+
158+
@spec get_state_root(Types.root()) :: Types.root() | nil
159+
def get_state_root(root) do
160+
with %{} = block <- Blocks.get_block(root) do
161+
block.state_root
162+
end
163+
end
164+
165+
defp check_valid_slot(slot, current_slot) when slot < current_slot, do: :ok
166+
167+
defp check_valid_slot(slot, _current_slot),
168+
do: {:error, "slot #{slot} cannot be greater than current slot"}
169+
end

lib/beacon_api/utils.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule BeaconApi.Utils do
22
@moduledoc """
33
Set of useful utilitary functions in the context of the Beacon API
44
"""
5-
alias LambdaEthereumConsensus.ForkChoice.Helpers
5+
alias BeaconApi.Helpers
66
alias LambdaEthereumConsensus.Utils.BitList
77

88
@spec parse_id(binary) :: Helpers.block_id()

lib/lambda_ethereum_consensus/beacon/beacon_node.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ defmodule LambdaEthereumConsensus.Beacon.BeaconNode do
55
require Logger
66

77
alias LambdaEthereumConsensus.Beacon.StoreSetup
8-
alias LambdaEthereumConsensus.ForkChoice.Helpers
8+
alias LambdaEthereumConsensus.ForkChoice.Head
99
alias LambdaEthereumConsensus.StateTransition.Cache
1010
alias LambdaEthereumConsensus.Store.Blocks
1111
alias LambdaEthereumConsensus.Store.BlockStates
@@ -36,7 +36,7 @@ defmodule LambdaEthereumConsensus.Beacon.BeaconNode do
3636

3737
time = :os.system_time(:second)
3838

39-
{:ok, head_root} = Helpers.get_head(store)
39+
{:ok, head_root} = Head.get_head(store)
4040
%{slot: head_slot} = Blocks.get_block!(head_root)
4141

4242
fork_choice_data = %{

lib/lambda_ethereum_consensus/fork_choice/fork_choice.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ defmodule LambdaEthereumConsensus.ForkChoice do
99
alias LambdaEthereumConsensus.Beacon.BeaconChain
1010
alias LambdaEthereumConsensus.Execution.ExecutionChain
1111
alias LambdaEthereumConsensus.ForkChoice.Handlers
12-
alias LambdaEthereumConsensus.ForkChoice.Helpers
12+
alias LambdaEthereumConsensus.ForkChoice.Head
1313
alias LambdaEthereumConsensus.P2P.Gossip.OperationsCollector
1414
alias LambdaEthereumConsensus.Store.Blocks
1515
alias LambdaEthereumConsensus.Store.StoreDb
@@ -166,7 +166,7 @@ defmodule LambdaEthereumConsensus.ForkChoice do
166166
@spec recompute_head(Store.t()) :: :ok
167167
def recompute_head(store) do
168168
persist_store(store)
169-
{:ok, head_root} = Helpers.get_head(store)
169+
{:ok, head_root} = Head.get_head(store)
170170
head_block = Blocks.get_block!(head_root)
171171

172172
Handlers.notify_forkchoice_update(store, head_block)

0 commit comments

Comments
 (0)