Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into ssz_support_nested_co…
Browse files Browse the repository at this point in the history
…ntainers
  • Loading branch information
f3r10 committed Dec 12, 2023
2 parents ef12292 + e0ddb7e commit 1b44478
Show file tree
Hide file tree
Showing 17 changed files with 541 additions and 213 deletions.
111 changes: 75 additions & 36 deletions lib/constants.ex
Original file line number Diff line number Diff line change
@@ -1,81 +1,120 @@
defmodule Constants do
@moduledoc """
Constants module with 0-arity functions.
The following values are (non-configurable) constants used throughout the specification.
"""

@spec genesis_epoch() :: integer
### Misc

@spec genesis_epoch() :: SszTypes.slot()
def genesis_epoch, do: 0

@spec genesis_slot() :: integer
@spec genesis_slot() :: SszTypes.slot()
def genesis_slot, do: 0

@spec bls_withdrawal_prefix() :: <<_::8>>
@far_future_epoch 2 ** 64 - 1

@spec far_future_epoch() :: non_neg_integer()
def far_future_epoch, do: @far_future_epoch

@spec base_rewards_per_epoch() :: non_neg_integer()
def base_rewards_per_epoch, do: 4

@spec deposit_contract_tree_depth() :: non_neg_integer()
def deposit_contract_tree_depth, do: 32

@spec justification_bits_length() :: non_neg_integer()
def justification_bits_length, do: 4

@spec endianness() :: atom()
def endianness, do: :little

@spec participation_flag_weights() :: list(non_neg_integer())
def participation_flag_weights,
do: [timely_source_weight(), timely_target_weight(), timely_head_weight()]

### Withdrawal prefixes

@spec bls_withdrawal_prefix() :: SszTypes.bytes1()
def bls_withdrawal_prefix, do: <<0>>

@spec eth1_address_withdrawal_prefix() :: <<_::8>>
@spec eth1_address_withdrawal_prefix() :: SszTypes.bytes1()
def eth1_address_withdrawal_prefix, do: <<1>>

@spec domain_beacon_attester() :: SszTypes.domain_type()
def domain_beacon_attester, do: <<1, 0, 0, 0>>
### Domain types

@spec domain_beacon_proposer() :: SszTypes.domain_type()
def domain_beacon_proposer, do: <<0, 0, 0, 0>>

@spec domain_deposit() :: SszTypes.domain_type()
def domain_deposit, do: <<3, 0, 0, 0>>
@spec domain_beacon_attester() :: SszTypes.domain_type()
def domain_beacon_attester, do: <<1, 0, 0, 0>>

@spec domain_randao() :: SszTypes.domain_type()
def domain_randao, do: <<2, 0, 0, 0>>

@spec domain_sync_committee() :: SszTypes.domain_type()
def domain_sync_committee, do: <<7, 0, 0, 0>>
@spec domain_deposit() :: SszTypes.domain_type()
def domain_deposit, do: <<3, 0, 0, 0>>

@spec domain_voluntary_exit() :: SszTypes.domain_type()
def domain_voluntary_exit, do: <<4, 0, 0, 0>>

@spec domain_selection_proof() :: SszTypes.domain_type()
def domain_selection_proof, do: <<5, 0, 0, 0>>

@spec domain_aggregate_and_proof() :: SszTypes.domain_type()
def domain_aggregate_and_proof, do: <<6, 0, 0, 0>>

@spec domain_application_mask() :: SszTypes.domain_type()
def domain_application_mask, do: <<0, 0, 0, 1>>

@spec domain_sync_committee() :: SszTypes.domain_type()
def domain_sync_committee, do: <<7, 0, 0, 0>>

@spec domain_sync_committee_selection_proof() :: SszTypes.domain_type()
def domain_sync_committee_selection_proof, do: <<8, 0, 0, 0>>

@spec domain_contribution_and_proof() :: SszTypes.domain_type()
def domain_contribution_and_proof, do: <<9, 0, 0, 0>>

@spec domain_bls_to_execution_change() :: SszTypes.domain_type()
def domain_bls_to_execution_change, do: <<10, 0, 0, 0>>

@spec timely_source_flag_index() :: integer
### Participation flag indices

@spec timely_source_flag_index() :: non_neg_integer()
def timely_source_flag_index, do: 0

@spec timely_target_flag_index() :: integer
@spec timely_target_flag_index() :: non_neg_integer()
def timely_target_flag_index, do: 1

@spec timely_head_flag_index() :: integer
@spec timely_head_flag_index() :: non_neg_integer()
def timely_head_flag_index, do: 2

@spec proposer_weight() :: integer
def proposer_weight, do: 8

@spec sync_reward_weight() :: integer
def sync_reward_weight, do: 2

@spec weight_denominator() :: integer
def weight_denominator, do: 64
### Incentivization weights

@spec participation_flag_weights() :: list(integer)
def participation_flag_weights,
do: [timely_source_weight(), timely_target_weight(), timely_head_weight()]

@spec base_reward_factor() :: integer
def base_reward_factor, do: 64

@spec timely_source_weight() :: integer
@spec timely_source_weight() :: non_neg_integer()
def timely_source_weight, do: 14

@spec timely_target_weight() :: integer
@spec timely_target_weight() :: non_neg_integer()
def timely_target_weight, do: 26

@spec timely_head_weight() :: integer
@spec timely_head_weight() :: non_neg_integer()
def timely_head_weight, do: 14

@spec far_future_epoch() :: integer
def far_future_epoch, do: 2 ** 64 - 1
@spec sync_reward_weight() :: non_neg_integer()
def sync_reward_weight, do: 2

@spec deposit_contract_tree_depth() :: integer
def deposit_contract_tree_depth, do: 32
@spec proposer_weight() :: non_neg_integer()
def proposer_weight, do: 8

@spec weight_denominator() :: non_neg_integer()
def weight_denominator, do: 64

@spec intervals_per_slot() :: integer
## Fork choice

@spec intervals_per_slot() :: non_neg_integer()
def intervals_per_slot, do: 3

@spec proposer_score_boost() :: non_neg_integer()
def proposer_score_boost, do: 3
end
81 changes: 31 additions & 50 deletions lib/lambda_ethereum_consensus/state_transition/accessors.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ defmodule LambdaEthereumConsensus.StateTransition.Accessors do
alias LambdaEthereumConsensus.Utils
alias SszTypes.{Attestation, BeaconState, IndexedAttestation, SyncCommittee, Validator}

@max_random_byte 2 ** 8 - 1

@doc """
Return the next sync committee, with possible pubkey duplicates.
"""
Expand Down Expand Up @@ -80,8 +82,6 @@ defmodule LambdaEthereumConsensus.StateTransition.Accessors do
validators,
sync_committee_indices
) do
max_random_byte = 2 ** 8 - 1

with {:ok, shuffled_index} <-
rem(index, active_validator_count)
|> Misc.compute_shuffled_index(active_validator_count, seed) do
Expand All @@ -90,10 +90,10 @@ defmodule LambdaEthereumConsensus.StateTransition.Accessors do
<<_::binary-size(rem(index, 32)), random_byte, _::binary>> =
SszEx.hash(seed <> Misc.uint64_to_bytes(div(index, 32)))

max_effective_balance = ChainSpec.get("MAX_EFFECTIVE_BALANCE")
effective_balance = Enum.fetch!(validators, candidate_index).effective_balance

if effective_balance * max_random_byte >=
ChainSpec.get("MAX_EFFECTIVE_BALANCE") * random_byte do
if effective_balance * @max_random_byte >= max_effective_balance * random_byte do
{:ok, sync_committee_indices |> List.insert_at(0, candidate_index)}
else
{:ok, sync_committee_indices}
Expand Down Expand Up @@ -278,7 +278,7 @@ defmodule LambdaEthereumConsensus.StateTransition.Accessors do

@spec get_base_reward_per_increment(BeaconState.t()) :: SszTypes.gwei()
def get_base_reward_per_increment(state) do
numerator = ChainSpec.get("EFFECTIVE_BALANCE_INCREMENT") * Constants.base_reward_factor()
numerator = ChainSpec.get("EFFECTIVE_BALANCE_INCREMENT") * ChainSpec.get("BASE_REWARD_FACTOR")
denominator = Math.integer_squareroot(get_total_active_balance(state))
div(numerator, denominator)
end
Expand Down Expand Up @@ -397,12 +397,11 @@ defmodule LambdaEthereumConsensus.StateTransition.Accessors do
"""
@spec get_seed(BeaconState.t(), SszTypes.epoch(), SszTypes.domain_type()) :: SszTypes.bytes32()
def get_seed(state, epoch, domain_type) do
mix =
get_randao_mix(
state,
epoch + ChainSpec.get("EPOCHS_PER_HISTORICAL_VECTOR") -
ChainSpec.get("MIN_SEED_LOOKAHEAD") - 1
)
future_epoch =
epoch + ChainSpec.get("EPOCHS_PER_HISTORICAL_VECTOR") -
ChainSpec.get("MIN_SEED_LOOKAHEAD") - 1

mix = get_randao_mix(state, future_epoch)

SszEx.hash(domain_type <> Misc.uint64_to_bytes(epoch) <> mix)
end
Expand Down Expand Up @@ -434,21 +433,14 @@ defmodule LambdaEthereumConsensus.StateTransition.Accessors do
@spec get_indexed_attestation(BeaconState.t(), Attestation.t()) ::
{:ok, IndexedAttestation.t()} | {:error, binary()}
def get_indexed_attestation(%BeaconState{} = state, attestation) do
case get_attesting_indices(state, attestation.data, attestation.aggregation_bits) do
{:ok, indices} ->
attesting_indices = indices
sorted_attesting_indices = Enum.sort(attesting_indices)

res = %IndexedAttestation{
attesting_indices: sorted_attesting_indices,
data: attestation.data,
signature: attestation.signature
}

{:ok, res}

{:error, reason} ->
{:error, reason}
with {:ok, indices} <-
get_attesting_indices(state, attestation.data, attestation.aggregation_bits) do
%IndexedAttestation{
attesting_indices: Enum.sort(indices),
data: attestation.data,
signature: attestation.signature
}
|> then(&{:ok, &1})
end
end

Expand All @@ -458,33 +450,22 @@ defmodule LambdaEthereumConsensus.StateTransition.Accessors do
@spec get_attesting_indices(BeaconState.t(), SszTypes.AttestationData.t(), SszTypes.bitlist()) ::
{:ok, MapSet.t()} | {:error, binary()}
def get_attesting_indices(%BeaconState{} = state, data, bits) do
case get_beacon_committee(state, data.slot, data.index) do
{:ok, committee} ->
bit_list = bitstring_to_list(bits)

res =
committee
|> Stream.with_index()
|> Stream.filter(fn {_value, index} -> Enum.at(bit_list, index) == "1" end)
|> Stream.map(fn {value, _index} -> value end)
|> MapSet.new()

{:ok, res}

{:error, reason} ->
{:error, reason}
with {:ok, committee} <- get_beacon_committee(state, data.slot, data.index) do
committee
|> Stream.with_index()
|> Stream.filter(fn {_value, index} -> participated?(bits, index) end)
|> Stream.map(fn {value, _index} -> value end)
|> MapSet.new()
|> then(&{:ok, &1})
end
end

def bitstring_to_list(binary) when is_binary(binary) do
binary
|> :binary.bin_to_list()
|> Enum.reduce("", fn byte, acc ->
acc <> Integer.to_string(byte, 2)
end)
# Exclude last bit
|> String.slice(0..-2)
|> String.graphemes()
defp participated?(bits, index) do
# The bit order inside the byte is reversed (e.g. bits[0] is the 8th bit).
# Here we keep the byte index the same, but reverse the bit index.
bit_index = index + 7 - 2 * rem(index, 8)
<<_::size(bit_index), flag::1, _::bits>> = bits
flag == 1
end

@doc """
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ defmodule LambdaEthereumConsensus.StateTransition.EpochProcessing do
current_epoch = Accessors.get_current_epoch(state)
next_epoch = current_epoch + 1
epochs_per_historical_vector = ChainSpec.get("EPOCHS_PER_HISTORICAL_VECTOR")
random_mix = Accessors.get_randao_mix(state, current_epoch)
randao_mix = Accessors.get_randao_mix(state, current_epoch)
index = rem(next_epoch, epochs_per_historical_vector)
new_randao_mixes = List.replace_at(randao_mixes, index, random_mix)
new_randao_mixes = List.replace_at(randao_mixes, index, randao_mix)
new_state = %BeaconState{state | randao_mixes: new_randao_mixes}
{:ok, new_state}
end
Expand Down
Loading

0 comments on commit 1b44478

Please sign in to comment.