Skip to content

Commit a604213

Browse files
committed
Notify Head now working from the ValidatorSet instead of Validators
1 parent 69150f2 commit a604213

File tree

3 files changed

+67
-31
lines changed

3 files changed

+67
-31
lines changed

lib/lambda_ethereum_consensus/validator/duties.ex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ defmodule LambdaEthereumConsensus.Validator.Duties do
4141
}
4242
end
4343

44-
@spec compute_proposers_for_epoch(BeaconState.t(), Types.epoch(), %{}) ::
45-
%{Types.slot() => non_neg_integer()}
44+
@spec compute_proposers_for_epoch(BeaconState.t(), Types.epoch(), %{}) :: any()
4645
def compute_proposers_for_epoch(%BeaconState{} = state, epoch, validators) do
4746
with {:ok, epoch} <- check_valid_epoch(state, epoch),
4847
{start_slot, end_slot} <- boundary_slots(epoch) do
48+
4949
start_slot..end_slot
5050
|> Enum.flat_map(fn slot ->
5151
{:ok, proposer_index} = Accessors.get_beacon_proposer_index(state, slot)
@@ -54,7 +54,7 @@ defmodule LambdaEthereumConsensus.Validator.Duties do
5454
do: [{slot, proposer_index}],
5555
else: []
5656
end)
57-
|> Map.new()
57+
|> then(&{:ok, Map.new(&1)})
5858
end
5959
end
6060

@@ -80,7 +80,7 @@ defmodule LambdaEthereumConsensus.Validator.Duties do
8080
slot :: Types.slot(),
8181
committee_index :: Types.uint64(),
8282
validator_index :: [{Types.validator_index(), Validator.validator()}]
83-
) :: attester_duty() | nil
83+
) :: [attester_duty()]
8484
defp compute_attester_dutys(state, epoch, slot, validators, committee_index) do
8585
with {:ok, committee} <- Accessors.get_beacon_committee(state, slot, committee_index) do
8686
committee
@@ -108,7 +108,7 @@ defmodule LambdaEthereumConsensus.Validator.Duties do
108108
end
109109
else
110110
{:error, _} ->
111-
nil
111+
[]
112112
end
113113
end
114114

lib/lambda_ethereum_consensus/validator/validator.ex

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ defmodule LambdaEthereumConsensus.Validator do
247247
end
248248

249249
@spec attest(state, Duties.attester_duty()) :: :ok
250-
defp attest(%{validator: validator} = state, current_duty) do
250+
def attest(%{validator: validator} = state, current_duty) do
251251
subnet_id = current_duty.subnet_id
252252
log_debug(validator.index, "attesting", slot: current_duty.slot, subnet_id: subnet_id)
253253

@@ -405,10 +405,9 @@ defmodule LambdaEthereumConsensus.Validator do
405405
end
406406

407407
@spec start_payload_builder(state, Types.slot(), Types.root()) :: state
408+
def start_payload_builder(%{payload_builder: {slot, root, _}} = state, slot, root), do: state
408409

409-
defp start_payload_builder(%{payload_builder: {slot, root, _}} = state, slot, root), do: state
410-
411-
defp start_payload_builder(%{validator: validator} = state, proposed_slot, head_root) do
410+
def start_payload_builder(%{validator: validator} = state, proposed_slot, head_root) do
412411
# TODO: handle reorgs and late blocks
413412
log_debug(validator.index, "starting building payload for slot #{proposed_slot}")
414413

lib/lambda_ethereum_consensus/validator/validator_set.ex

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ defmodule LambdaEthereumConsensus.ValidatorSet do
55
simplify the delegation of work.
66
"""
77

8-
defstruct epoch: nil, slot: nil, head_root: nil, validators: %{uninitialized: []}
8+
defstruct epoch: nil, slot: nil, head_root: nil, duties: %{}, validators: []
99

1010
require Logger
1111

@@ -19,11 +19,12 @@ defmodule LambdaEthereumConsensus.ValidatorSet do
1919
epoch: Types.epoch() | nil,
2020
slot: Types.slot() | nil,
2121
head_root: Types.root() | nil,
22+
duties: %{Types.epoch() => %{proposers: Duties.proposers(), attesters: Duties.attesters()}},
2223
validators: validators()
2324
}
2425

2526
@doc """
26-
Initiate the pool of validators, given the slot and head root.
27+
Initiate the set of validators, given the slot and head root.
2728
"""
2829
@spec init(Types.slot(), Types.root()) :: t()
2930
def init(slot, head_root) do
@@ -57,8 +58,8 @@ defmodule LambdaEthereumConsensus.ValidatorSet do
5758

5859
Logger.info("[Validator] Initialized #{Enum.count(validators)} validators")
5960

60-
proposers = Duties.compute_proposers_for_epoch(beacon, epoch, validators)
61-
attesters = Duties.compute_attesters_for_epoch(beacon, epoch, validators)
61+
{:ok, proposers} = Duties.compute_proposers_for_epoch(beacon, epoch, validators)
62+
{:ok, attesters} = Duties.compute_attesters_for_epoch(beacon, epoch, validators)
6263

6364
Logger.info("[Validator] Proposers: #{inspect(proposers, pretty: true)}")
6465
Logger.info("[Validator] Attesters: #{inspect(attesters, pretty: true)}")
@@ -67,11 +68,11 @@ defmodule LambdaEthereumConsensus.ValidatorSet do
6768
epoch: epoch,
6869
slot: slot,
6970
head_root: head_root,
70-
validators: %{
71+
duties: %{epoch => %{
7172
proposers: proposers,
72-
attesters: attesters,
73-
uninitialized: validators
74-
}
73+
attesters: attesters
74+
}},
75+
validators: validators
7576
}
7677
end
7778

@@ -84,26 +85,62 @@ defmodule LambdaEthereumConsensus.ValidatorSet do
8485
Notify all validators of a new head.
8586
"""
8687
@spec notify_head(t(), Types.slot(), Types.root()) :: t()
87-
def notify_head(%{validators: %{uninitialized: validators}} = pool, slot, head_root) do
88-
uninitialized_validators =
89-
maybe_debug_notify(
90-
fn ->
91-
Map.new(validators, fn {k, v} ->
92-
{k, Validator.handle_new_head(slot, head_root, v)}
93-
end)
94-
end,
95-
{:new_head, slot, head_root}
96-
)
88+
def notify_head(%{validators: validators, epoch: epoch} = set, slot, head_root) do
89+
set
90+
|> attest(epoch, slot)
91+
|> build_next_payload(epoch, slot, head_root)
92+
|> update_state(slot, head_root)
93+
end
9794

98-
%{pool | validators: %{uninitialized: uninitialized_validators}}
95+
defp update_state(set, slot, head_root) do
96+
%{set | slot: slot, head_root: head_root}
9997
end
10098

99+
defp attest(set, epoch, slot) do
100+
updated_duties =
101+
set
102+
|> current_attesters(epoch, slot)
103+
|> Enum.map(fn {validator, duty} ->
104+
Validator.attest(validator, duty)
105+
106+
# Duty.attested(duty)
107+
%{duty | attested?: true}
108+
end)
109+
110+
%{set | duties: put_in(set.duties, [set.epoch, :attesters, slot], updated_duties)}
111+
end
112+
113+
defp build_next_payload(set, epoch, slot, head_root) do
114+
set
115+
|> proposer(epoch, slot + 1)
116+
|> case do
117+
nil -> set
118+
validator_index ->
119+
validator = Map.get(set.validators, validator_index)
120+
updated_validator = Validator.start_payload_builder(validator, slot + 1, head_root)
121+
122+
%{set | validators: Map.put(set.validators, updated_validator.validator.index, updated_validator)}
123+
end
124+
end
125+
126+
defp current_attesters(set, epoch, slot) do
127+
attesters(set, epoch, slot)
128+
|> Enum.flat_map(fn
129+
%{attested?: false} = duty -> [{Map.get(set.validators, duty.validator_index), duty}]
130+
_ -> []
131+
end)
132+
end
133+
134+
defp proposer(set, epoch, slot), do: get_in(set.duties, [epoch, :proposers, slot])
135+
defp attesters(set, epoch, slot), do: get_in(set.duties, [epoch, :attesters, slot]) || []
136+
137+
101138
@doc """
102139
Notify all validators of a new tick.
103140
"""
104141
@spec notify_tick(t(), tuple()) :: t()
105-
def notify_tick(%{validators: %{uninitialized: validators}} = pool, slot_data) do
106-
uninitialized_validators =
142+
def notify_tick(%{validators: validators} = set, slot_data) do
143+
validators =
107144
maybe_debug_notify(
108145
fn ->
109146
Map.new(validators, fn {k, v} ->
@@ -113,7 +150,7 @@ defmodule LambdaEthereumConsensus.ValidatorSet do
113150
{:on_tick, slot_data}
114151
)
115152

116-
%{pool | validators: %{uninitialized: uninitialized_validators}}
153+
%{set | validators: validators}
117154
end
118155

119156
defp maybe_debug_notify(fun, data) do

0 commit comments

Comments
 (0)