Skip to content

feat: electra container and ssz support #1400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Apr 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion lib/lambda_ethereum_consensus/validator/block_builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ defmodule LambdaEthereumConsensus.Validator.BlockBuilder do
block_request.slot,
block_request.parent_root
),
execution_payload: execution_payload
execution_payload: execution_payload,
execution_requests: %Types.ExecutionRequests{
deposits: [],
withdrawals: [],
consolidations: []
}
}
}}
end
Expand Down
4 changes: 3 additions & 1 deletion lib/lambda_ethereum_consensus/validator/validator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,9 @@ defmodule LambdaEthereumConsensus.Validator do
%Attestation{
data: attestation_data,
aggregation_bits: bits,
signature: signature
signature: signature,
# Not implemented yet, part of EIP7549
committee_bits: BitList.zero(committee_length)
}
end

Expand Down
29 changes: 21 additions & 8 deletions lib/types/beacon_chain/attestation.ex
Original file line number Diff line number Diff line change
@@ -1,45 +1,58 @@
defmodule Types.Attestation do
@moduledoc """
Struct definition for `AttestationMainnet`.
Struct definition for `Attestation`.
Related definitions in `native/ssz_nif/src/types/`.

aggregation_bits is a bit list that has the size of a committee. Each individual bit is set if
the validator corresponding to that bit participated in attesting.
"""
alias LambdaEthereumConsensus.Utils.BitList
alias LambdaEthereumConsensus.Utils.BitVector

use LambdaEthereumConsensus.Container

fields = [
:aggregation_bits,
:data,
:signature
:signature,
:committee_bits
]

@enforce_keys fields
defstruct fields

@type t :: %__MODULE__{
# MAX_VALIDATORS_PER_COMMITTEE
# [Modified in Electra:EIP7549]
aggregation_bits: Types.bitlist(),
data: Types.AttestationData.t(),
signature: Types.bls_signature()
signature: Types.bls_signature(),
# [New in Electra:EIP7549]
committee_bits: BitVector.t()
}

@impl LambdaEthereumConsensus.Container
def schema() do
[
{:aggregation_bits, {:bitlist, ChainSpec.get("MAX_VALIDATORS_PER_COMMITTEE")}},
{:aggregation_bits,
{:bitlist,
ChainSpec.get("MAX_VALIDATORS_PER_COMMITTEE") * ChainSpec.get("MAX_COMMITTEES_PER_SLOT")}},
{:data, Types.AttestationData},
{:signature, TypeAliases.bls_signature()}
{:signature, TypeAliases.bls_signature()},
{:committee_bits, {:bitvector, ChainSpec.get("MAX_COMMITTEES_PER_SLOT")}}
]
end

def encode(%__MODULE__{} = map) do
Map.update!(map, :aggregation_bits, &BitList.to_bytes/1)
map
|> Map.update!(:aggregation_bits, &BitList.to_bytes/1)
|> Map.update!(:committee_bits, &BitVector.to_bytes/1)
end

def decode(%__MODULE__{} = map) do
Map.update!(map, :aggregation_bits, &BitList.new/1)
map
|> Map.update!(:aggregation_bits, &BitList.new/1)
|> Map.update!(:committee_bits, fn bits ->
BitVector.new(bits, ChainSpec.get("MAX_COMMITTEES_PER_SLOT"))
end)
end
end
18 changes: 13 additions & 5 deletions lib/types/beacon_chain/beacon_block_body.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ defmodule Types.BeaconBlockBody do
:sync_aggregate,
:execution_payload,
:bls_to_execution_changes,
:blob_kzg_commitments
:blob_kzg_commitments,
# New Electra fields
:execution_requests
]

@enforce_keys fields
Expand All @@ -42,7 +44,9 @@ defmodule Types.BeaconBlockBody do
# max MAX_BLS_TO_EXECUTION_CHANGES
bls_to_execution_changes: list(Types.SignedBLSToExecutionChange.t()),
# max MAX_BLOB_COMMITMENTS_PER_BLOCK
blob_kzg_commitments: list(Types.kzg_commitment())
blob_kzg_commitments: list(Types.kzg_commitment()),
# New in Electra
execution_requests: Types.ExecutionRequests.t()
}

@impl LambdaEthereumConsensus.Container
Expand All @@ -53,17 +57,21 @@ defmodule Types.BeaconBlockBody do
graffiti: TypeAliases.bytes32(),
proposer_slashings:
{:list, Types.ProposerSlashing, ChainSpec.get("MAX_PROPOSER_SLASHINGS")},
# [Modified in Electra:EIP7549]
attester_slashings:
{:list, Types.AttesterSlashing, ChainSpec.get("MAX_ATTESTER_SLASHINGS")},
attestations: {:list, Types.Attestation, ChainSpec.get("MAX_ATTESTATIONS")},
{:list, Types.AttesterSlashing, ChainSpec.get("MAX_ATTESTER_SLASHINGS_ELECTRA")},
# [Modified in Electra:EIP7549]
attestations: {:list, Types.Attestation, ChainSpec.get("MAX_ATTESTATIONS_ELECTRA")},
deposits: {:list, Types.Deposit, ChainSpec.get("MAX_DEPOSITS")},
voluntary_exits: {:list, Types.SignedVoluntaryExit, ChainSpec.get("MAX_VOLUNTARY_EXITS")},
sync_aggregate: Types.SyncAggregate,
execution_payload: Types.ExecutionPayload,
bls_to_execution_changes:
{:list, Types.SignedBLSToExecutionChange, ChainSpec.get("MAX_BLS_TO_EXECUTION_CHANGES")},
blob_kzg_commitments:
{:list, TypeAliases.kzg_commitment(), ChainSpec.get("MAX_BLOB_COMMITMENTS_PER_BLOCK")}
{:list, TypeAliases.kzg_commitment(), ChainSpec.get("MAX_BLOB_COMMITMENTS_PER_BLOCK")},
# New in Electra
execution_requests: Types.ExecutionRequests
]
end
end
46 changes: 43 additions & 3 deletions lib/types/beacon_chain/beacon_state.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,17 @@ defmodule Types.BeaconState do
:latest_execution_payload_header,
:next_withdrawal_index,
:next_withdrawal_validator_index,
:historical_summaries
:historical_summaries,
# New Electra fields
:deposit_requests_start_index,
:deposit_balance_to_consume,
:exit_balance_to_consume,
:earliest_exit_epoch,
:consolidation_balance_to_consume,
:earliest_consolidation_epoch,
:pending_deposits,
:pending_partial_withdrawals,
:pending_consolidations
]

@enforce_keys fields
Expand Down Expand Up @@ -105,7 +115,25 @@ defmodule Types.BeaconState do
# Deep history valid from Capella onwards
# [New in Capella]
# HISTORICAL_ROOTS_LIMIT
historical_summaries: list(Types.HistoricalSummary.t())
historical_summaries: list(Types.HistoricalSummary.t()),
# [New in Electra:EIP6110]
deposit_requests_start_index: Types.uint64(),
# [New in Electra:EIP7251]
deposit_balance_to_consume: Types.gwei(),
# [New in Electra:EIP7251]
exit_balance_to_consume: Types.gwei(),
# [New in Electra:EIP7251]
earliest_exit_epoch: Types.epoch(),
# [New in Electra:EIP7251]
consolidation_balance_to_consume: Types.gwei(),
# [New in Electra:EIP7251]
earliest_consolidation_epoch: Types.epoch(),
# [New in Electra:EIP7251]
pending_deposits: list(Types.PendingDeposit.t()),
# [New in Electra:EIP7251]
pending_partial_withdrawals: list(Types.PendingPartialWithdrawal.t()),
# [New in Electra:EIP7251]
pending_consolidations: list(Types.PendingConsolidation.t())
}

@impl LambdaEthereumConsensus.Container
Expand Down Expand Up @@ -145,7 +173,19 @@ defmodule Types.BeaconState do
{:next_withdrawal_index, TypeAliases.withdrawal_index()},
{:next_withdrawal_validator_index, TypeAliases.validator_index()},
{:historical_summaries,
{:list, Types.HistoricalSummary, ChainSpec.get("HISTORICAL_ROOTS_LIMIT")}}
{:list, Types.HistoricalSummary, ChainSpec.get("HISTORICAL_ROOTS_LIMIT")}},
# New Electra fields
{:deposit_requests_start_index, TypeAliases.uint64()},
{:deposit_balance_to_consume, TypeAliases.gwei()},
{:exit_balance_to_consume, TypeAliases.gwei()},
{:earliest_exit_epoch, TypeAliases.epoch()},
{:consolidation_balance_to_consume, TypeAliases.gwei()},
{:earliest_consolidation_epoch, TypeAliases.epoch()},
{:pending_deposits, {:list, Types.PendingDeposit, ChainSpec.get("PENDING_DEPOSITS_LIMIT")}},
{:pending_partial_withdrawals,
{:list, Types.PendingPartialWithdrawal, ChainSpec.get("PENDING_PARTIAL_WITHDRAWALS_LIMIT")}},
{:pending_consolidations,
{:list, Types.PendingConsolidation, ChainSpec.get("PENDING_CONSOLIDATIONS_LIMIT")}}
]
end

Expand Down
27 changes: 27 additions & 0 deletions lib/types/beacon_chain/consolidation_request.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule Types.ConsolidationRequest do
@moduledoc """
Struct definition for `ConsolidationRequest`.
Added in Electra fork (EIP7251).
"""

use LambdaEthereumConsensus.Container

fields = [:source_address, :source_pubkey, :target_pubkey]
@enforce_keys fields
defstruct fields

@type t :: %__MODULE__{
source_address: Types.execution_address(),
source_pubkey: Types.bls_pubkey(),
target_pubkey: Types.bls_pubkey()
}

@impl LambdaEthereumConsensus.Container
def schema() do
[
{:source_address, TypeAliases.execution_address()},
{:source_pubkey, TypeAliases.bls_pubkey()},
{:target_pubkey, TypeAliases.bls_pubkey()}
]
end
end
31 changes: 31 additions & 0 deletions lib/types/beacon_chain/deposit_request.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule Types.DepositRequest do
@moduledoc """
Struct definition for `DepositRequest`.
Added in Electra fork (EIP6110).
"""

use LambdaEthereumConsensus.Container

fields = [:pubkey, :withdrawal_credentials, :amount, :signature, :index]
@enforce_keys fields
defstruct fields

@type t :: %__MODULE__{
pubkey: Types.bls_pubkey(),
withdrawal_credentials: Types.bytes32(),
amount: Types.gwei(),
signature: Types.bls_signature(),
index: Types.uint64()
}

@impl LambdaEthereumConsensus.Container
def schema() do
[
{:pubkey, TypeAliases.bls_pubkey()},
{:withdrawal_credentials, TypeAliases.bytes32()},
{:amount, TypeAliases.gwei()},
{:signature, TypeAliases.bls_signature()},
{:index, TypeAliases.uint64()}
]
end
end
31 changes: 31 additions & 0 deletions lib/types/beacon_chain/execution_requests.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule Types.ExecutionRequests do
@moduledoc """
Struct definition for `ExecutionRequests`.
Added in Electra fork.
"""

use LambdaEthereumConsensus.Container

fields = [:deposits, :withdrawals, :consolidations]
@enforce_keys fields
defstruct fields

@type t :: %__MODULE__{
deposits: list(Types.DepositRequest.t()),
withdrawals: list(Types.WithdrawalRequest.t()),
consolidations: list(Types.ConsolidationRequest.t())
}

@impl LambdaEthereumConsensus.Container
def schema() do
[
{:deposits,
{:list, Types.DepositRequest, ChainSpec.get("MAX_DEPOSIT_REQUESTS_PER_PAYLOAD")}},
{:withdrawals,
{:list, Types.WithdrawalRequest, ChainSpec.get("MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD")}},
{:consolidations,
{:list, Types.ConsolidationRequest,
ChainSpec.get("MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD")}}
]
end
end
5 changes: 3 additions & 2 deletions lib/types/beacon_chain/indexed_attestation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defmodule Types.IndexedAttestation do
defstruct fields

@type t :: %__MODULE__{
# max size is MAX_VALIDATORS_PER_COMMITTEE
# [Modified in Electra:EIP7549]
attesting_indices: list(Types.validator_index()),
data: Types.AttestationData.t(),
signature: Types.bls_signature()
Expand All @@ -33,7 +33,8 @@ defmodule Types.IndexedAttestation do
def schema() do
[
{:attesting_indices,
{:list, TypeAliases.validator_index(), ChainSpec.get("MAX_VALIDATORS_PER_COMMITTEE")}},
{:list, TypeAliases.validator_index(),
ChainSpec.get("MAX_VALIDATORS_PER_COMMITTEE") * ChainSpec.get("MAX_COMMITTEES_PER_SLOT")}},
{:data, Types.AttestationData},
{:signature, TypeAliases.bls_signature()}
]
Expand Down
25 changes: 25 additions & 0 deletions lib/types/beacon_chain/pending_consolidation.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
defmodule Types.PendingConsolidation do
@moduledoc """
Struct definition for `PendingConsolidation`.
Added in Electra fork (EIP7251).
"""

use LambdaEthereumConsensus.Container

fields = [:source_index, :target_index]
@enforce_keys fields
defstruct fields

@type t :: %__MODULE__{
source_index: Types.validator_index(),
target_index: Types.validator_index()
}

@impl LambdaEthereumConsensus.Container
def schema() do
[
{:source_index, TypeAliases.validator_index()},
{:target_index, TypeAliases.validator_index()}
]
end
end
31 changes: 31 additions & 0 deletions lib/types/beacon_chain/pending_deposit.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule Types.PendingDeposit do
@moduledoc """
Struct definition for `PendingDeposit`.
Added in Electra fork (EIP7251).
"""

use LambdaEthereumConsensus.Container

fields = [:pubkey, :withdrawal_credentials, :amount, :signature, :slot]
@enforce_keys fields
defstruct fields

@type t :: %__MODULE__{
pubkey: Types.bls_pubkey(),
withdrawal_credentials: Types.bytes32(),
amount: Types.gwei(),
signature: Types.bls_signature(),
slot: Types.slot()
}

@impl LambdaEthereumConsensus.Container
def schema() do
[
{:pubkey, TypeAliases.bls_pubkey()},
{:withdrawal_credentials, TypeAliases.bytes32()},
{:amount, TypeAliases.gwei()},
{:signature, TypeAliases.bls_signature()},
{:slot, TypeAliases.slot()}
]
end
end
Loading
Loading