Skip to content

Commit f4633c9

Browse files
committed
feat: electra container and ssz support (#1400)
1 parent be8f62a commit f4633c9

25 files changed

+588
-31
lines changed

lib/lambda_ethereum_consensus/validator/block_builder.ex

+6-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,12 @@ defmodule LambdaEthereumConsensus.Validator.BlockBuilder do
9595
block_request.slot,
9696
block_request.parent_root
9797
),
98-
execution_payload: execution_payload
98+
execution_payload: execution_payload,
99+
execution_requests: %Types.ExecutionRequests{
100+
deposits: [],
101+
withdrawals: [],
102+
consolidations: []
103+
}
99104
}
100105
}}
101106
end

lib/lambda_ethereum_consensus/validator/validator.ex

+3-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,9 @@ defmodule LambdaEthereumConsensus.Validator do
175175
%Attestation{
176176
data: attestation_data,
177177
aggregation_bits: bits,
178-
signature: signature
178+
signature: signature,
179+
# Not implemented yet, part of EIP7549
180+
committee_bits: BitList.zero(committee_length)
179181
}
180182
end
181183

lib/types/beacon_chain/attestation.ex

+21-8
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,58 @@
11
defmodule Types.Attestation do
22
@moduledoc """
3-
Struct definition for `AttestationMainnet`.
3+
Struct definition for `Attestation`.
44
Related definitions in `native/ssz_nif/src/types/`.
55
66
aggregation_bits is a bit list that has the size of a committee. Each individual bit is set if
77
the validator corresponding to that bit participated in attesting.
88
"""
99
alias LambdaEthereumConsensus.Utils.BitList
10+
alias LambdaEthereumConsensus.Utils.BitVector
1011

1112
use LambdaEthereumConsensus.Container
1213

1314
fields = [
1415
:aggregation_bits,
1516
:data,
16-
:signature
17+
:signature,
18+
:committee_bits
1719
]
1820

1921
@enforce_keys fields
2022
defstruct fields
2123

2224
@type t :: %__MODULE__{
23-
# MAX_VALIDATORS_PER_COMMITTEE
25+
# [Modified in Electra:EIP7549]
2426
aggregation_bits: Types.bitlist(),
2527
data: Types.AttestationData.t(),
26-
signature: Types.bls_signature()
28+
signature: Types.bls_signature(),
29+
# [New in Electra:EIP7549]
30+
committee_bits: BitVector.t()
2731
}
2832

2933
@impl LambdaEthereumConsensus.Container
3034
def schema() do
3135
[
32-
{:aggregation_bits, {:bitlist, ChainSpec.get("MAX_VALIDATORS_PER_COMMITTEE")}},
36+
{:aggregation_bits,
37+
{:bitlist,
38+
ChainSpec.get("MAX_VALIDATORS_PER_COMMITTEE") * ChainSpec.get("MAX_COMMITTEES_PER_SLOT")}},
3339
{:data, Types.AttestationData},
34-
{:signature, TypeAliases.bls_signature()}
40+
{:signature, TypeAliases.bls_signature()},
41+
{:committee_bits, {:bitvector, ChainSpec.get("MAX_COMMITTEES_PER_SLOT")}}
3542
]
3643
end
3744

3845
def encode(%__MODULE__{} = map) do
39-
Map.update!(map, :aggregation_bits, &BitList.to_bytes/1)
46+
map
47+
|> Map.update!(:aggregation_bits, &BitList.to_bytes/1)
48+
|> Map.update!(:committee_bits, &BitVector.to_bytes/1)
4049
end
4150

4251
def decode(%__MODULE__{} = map) do
43-
Map.update!(map, :aggregation_bits, &BitList.new/1)
52+
map
53+
|> Map.update!(:aggregation_bits, &BitList.new/1)
54+
|> Map.update!(:committee_bits, fn bits ->
55+
BitVector.new(bits, ChainSpec.get("MAX_COMMITTEES_PER_SLOT"))
56+
end)
4457
end
4558
end

lib/types/beacon_chain/beacon_block_body.ex

+13-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ defmodule Types.BeaconBlockBody do
1717
:sync_aggregate,
1818
:execution_payload,
1919
:bls_to_execution_changes,
20-
:blob_kzg_commitments
20+
:blob_kzg_commitments,
21+
# New Electra fields
22+
:execution_requests
2123
]
2224

2325
@enforce_keys fields
@@ -42,7 +44,9 @@ defmodule Types.BeaconBlockBody do
4244
# max MAX_BLS_TO_EXECUTION_CHANGES
4345
bls_to_execution_changes: list(Types.SignedBLSToExecutionChange.t()),
4446
# max MAX_BLOB_COMMITMENTS_PER_BLOCK
45-
blob_kzg_commitments: list(Types.kzg_commitment())
47+
blob_kzg_commitments: list(Types.kzg_commitment()),
48+
# New in Electra
49+
execution_requests: Types.ExecutionRequests.t()
4650
}
4751

4852
@impl LambdaEthereumConsensus.Container
@@ -53,17 +57,21 @@ defmodule Types.BeaconBlockBody do
5357
graffiti: TypeAliases.bytes32(),
5458
proposer_slashings:
5559
{:list, Types.ProposerSlashing, ChainSpec.get("MAX_PROPOSER_SLASHINGS")},
60+
# [Modified in Electra:EIP7549]
5661
attester_slashings:
57-
{:list, Types.AttesterSlashing, ChainSpec.get("MAX_ATTESTER_SLASHINGS")},
58-
attestations: {:list, Types.Attestation, ChainSpec.get("MAX_ATTESTATIONS")},
62+
{:list, Types.AttesterSlashing, ChainSpec.get("MAX_ATTESTER_SLASHINGS_ELECTRA")},
63+
# [Modified in Electra:EIP7549]
64+
attestations: {:list, Types.Attestation, ChainSpec.get("MAX_ATTESTATIONS_ELECTRA")},
5965
deposits: {:list, Types.Deposit, ChainSpec.get("MAX_DEPOSITS")},
6066
voluntary_exits: {:list, Types.SignedVoluntaryExit, ChainSpec.get("MAX_VOLUNTARY_EXITS")},
6167
sync_aggregate: Types.SyncAggregate,
6268
execution_payload: Types.ExecutionPayload,
6369
bls_to_execution_changes:
6470
{:list, Types.SignedBLSToExecutionChange, ChainSpec.get("MAX_BLS_TO_EXECUTION_CHANGES")},
6571
blob_kzg_commitments:
66-
{:list, TypeAliases.kzg_commitment(), ChainSpec.get("MAX_BLOB_COMMITMENTS_PER_BLOCK")}
72+
{:list, TypeAliases.kzg_commitment(), ChainSpec.get("MAX_BLOB_COMMITMENTS_PER_BLOCK")},
73+
# New in Electra
74+
execution_requests: Types.ExecutionRequests
6775
]
6876
end
6977
end

lib/types/beacon_chain/beacon_state.ex

+43-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,17 @@ defmodule Types.BeaconState do
3939
:latest_execution_payload_header,
4040
:next_withdrawal_index,
4141
:next_withdrawal_validator_index,
42-
:historical_summaries
42+
:historical_summaries,
43+
# New Electra fields
44+
:deposit_requests_start_index,
45+
:deposit_balance_to_consume,
46+
:exit_balance_to_consume,
47+
:earliest_exit_epoch,
48+
:consolidation_balance_to_consume,
49+
:earliest_consolidation_epoch,
50+
:pending_deposits,
51+
:pending_partial_withdrawals,
52+
:pending_consolidations
4353
]
4454

4555
@enforce_keys fields
@@ -105,7 +115,25 @@ defmodule Types.BeaconState do
105115
# Deep history valid from Capella onwards
106116
# [New in Capella]
107117
# HISTORICAL_ROOTS_LIMIT
108-
historical_summaries: list(Types.HistoricalSummary.t())
118+
historical_summaries: list(Types.HistoricalSummary.t()),
119+
# [New in Electra:EIP6110]
120+
deposit_requests_start_index: Types.uint64(),
121+
# [New in Electra:EIP7251]
122+
deposit_balance_to_consume: Types.gwei(),
123+
# [New in Electra:EIP7251]
124+
exit_balance_to_consume: Types.gwei(),
125+
# [New in Electra:EIP7251]
126+
earliest_exit_epoch: Types.epoch(),
127+
# [New in Electra:EIP7251]
128+
consolidation_balance_to_consume: Types.gwei(),
129+
# [New in Electra:EIP7251]
130+
earliest_consolidation_epoch: Types.epoch(),
131+
# [New in Electra:EIP7251]
132+
pending_deposits: list(Types.PendingDeposit.t()),
133+
# [New in Electra:EIP7251]
134+
pending_partial_withdrawals: list(Types.PendingPartialWithdrawal.t()),
135+
# [New in Electra:EIP7251]
136+
pending_consolidations: list(Types.PendingConsolidation.t())
109137
}
110138

111139
@impl LambdaEthereumConsensus.Container
@@ -145,7 +173,19 @@ defmodule Types.BeaconState do
145173
{:next_withdrawal_index, TypeAliases.withdrawal_index()},
146174
{:next_withdrawal_validator_index, TypeAliases.validator_index()},
147175
{:historical_summaries,
148-
{:list, Types.HistoricalSummary, ChainSpec.get("HISTORICAL_ROOTS_LIMIT")}}
176+
{:list, Types.HistoricalSummary, ChainSpec.get("HISTORICAL_ROOTS_LIMIT")}},
177+
# New Electra fields
178+
{:deposit_requests_start_index, TypeAliases.uint64()},
179+
{:deposit_balance_to_consume, TypeAliases.gwei()},
180+
{:exit_balance_to_consume, TypeAliases.gwei()},
181+
{:earliest_exit_epoch, TypeAliases.epoch()},
182+
{:consolidation_balance_to_consume, TypeAliases.gwei()},
183+
{:earliest_consolidation_epoch, TypeAliases.epoch()},
184+
{:pending_deposits, {:list, Types.PendingDeposit, ChainSpec.get("PENDING_DEPOSITS_LIMIT")}},
185+
{:pending_partial_withdrawals,
186+
{:list, Types.PendingPartialWithdrawal, ChainSpec.get("PENDING_PARTIAL_WITHDRAWALS_LIMIT")}},
187+
{:pending_consolidations,
188+
{:list, Types.PendingConsolidation, ChainSpec.get("PENDING_CONSOLIDATIONS_LIMIT")}}
149189
]
150190
end
151191

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
defmodule Types.ConsolidationRequest do
2+
@moduledoc """
3+
Struct definition for `ConsolidationRequest`.
4+
Added in Electra fork (EIP7251).
5+
"""
6+
7+
use LambdaEthereumConsensus.Container
8+
9+
fields = [:source_address, :source_pubkey, :target_pubkey]
10+
@enforce_keys fields
11+
defstruct fields
12+
13+
@type t :: %__MODULE__{
14+
source_address: Types.execution_address(),
15+
source_pubkey: Types.bls_pubkey(),
16+
target_pubkey: Types.bls_pubkey()
17+
}
18+
19+
@impl LambdaEthereumConsensus.Container
20+
def schema() do
21+
[
22+
{:source_address, TypeAliases.execution_address()},
23+
{:source_pubkey, TypeAliases.bls_pubkey()},
24+
{:target_pubkey, TypeAliases.bls_pubkey()}
25+
]
26+
end
27+
end
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
defmodule Types.DepositRequest do
2+
@moduledoc """
3+
Struct definition for `DepositRequest`.
4+
Added in Electra fork (EIP6110).
5+
"""
6+
7+
use LambdaEthereumConsensus.Container
8+
9+
fields = [:pubkey, :withdrawal_credentials, :amount, :signature, :index]
10+
@enforce_keys fields
11+
defstruct fields
12+
13+
@type t :: %__MODULE__{
14+
pubkey: Types.bls_pubkey(),
15+
withdrawal_credentials: Types.bytes32(),
16+
amount: Types.gwei(),
17+
signature: Types.bls_signature(),
18+
index: Types.uint64()
19+
}
20+
21+
@impl LambdaEthereumConsensus.Container
22+
def schema() do
23+
[
24+
{:pubkey, TypeAliases.bls_pubkey()},
25+
{:withdrawal_credentials, TypeAliases.bytes32()},
26+
{:amount, TypeAliases.gwei()},
27+
{:signature, TypeAliases.bls_signature()},
28+
{:index, TypeAliases.uint64()}
29+
]
30+
end
31+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
defmodule Types.ExecutionRequests do
2+
@moduledoc """
3+
Struct definition for `ExecutionRequests`.
4+
Added in Electra fork.
5+
"""
6+
7+
use LambdaEthereumConsensus.Container
8+
9+
fields = [:deposits, :withdrawals, :consolidations]
10+
@enforce_keys fields
11+
defstruct fields
12+
13+
@type t :: %__MODULE__{
14+
deposits: list(Types.DepositRequest.t()),
15+
withdrawals: list(Types.WithdrawalRequest.t()),
16+
consolidations: list(Types.ConsolidationRequest.t())
17+
}
18+
19+
@impl LambdaEthereumConsensus.Container
20+
def schema() do
21+
[
22+
{:deposits,
23+
{:list, Types.DepositRequest, ChainSpec.get("MAX_DEPOSIT_REQUESTS_PER_PAYLOAD")}},
24+
{:withdrawals,
25+
{:list, Types.WithdrawalRequest, ChainSpec.get("MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD")}},
26+
{:consolidations,
27+
{:list, Types.ConsolidationRequest,
28+
ChainSpec.get("MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD")}}
29+
]
30+
end
31+
end

lib/types/beacon_chain/indexed_attestation.ex

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ defmodule Types.IndexedAttestation do
2323
defstruct fields
2424

2525
@type t :: %__MODULE__{
26-
# max size is MAX_VALIDATORS_PER_COMMITTEE
26+
# [Modified in Electra:EIP7549]
2727
attesting_indices: list(Types.validator_index()),
2828
data: Types.AttestationData.t(),
2929
signature: Types.bls_signature()
@@ -33,7 +33,8 @@ defmodule Types.IndexedAttestation do
3333
def schema() do
3434
[
3535
{:attesting_indices,
36-
{:list, TypeAliases.validator_index(), ChainSpec.get("MAX_VALIDATORS_PER_COMMITTEE")}},
36+
{:list, TypeAliases.validator_index(),
37+
ChainSpec.get("MAX_VALIDATORS_PER_COMMITTEE") * ChainSpec.get("MAX_COMMITTEES_PER_SLOT")}},
3738
{:data, Types.AttestationData},
3839
{:signature, TypeAliases.bls_signature()}
3940
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
defmodule Types.PendingConsolidation do
2+
@moduledoc """
3+
Struct definition for `PendingConsolidation`.
4+
Added in Electra fork (EIP7251).
5+
"""
6+
7+
use LambdaEthereumConsensus.Container
8+
9+
fields = [:source_index, :target_index]
10+
@enforce_keys fields
11+
defstruct fields
12+
13+
@type t :: %__MODULE__{
14+
source_index: Types.validator_index(),
15+
target_index: Types.validator_index()
16+
}
17+
18+
@impl LambdaEthereumConsensus.Container
19+
def schema() do
20+
[
21+
{:source_index, TypeAliases.validator_index()},
22+
{:target_index, TypeAliases.validator_index()}
23+
]
24+
end
25+
end
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
defmodule Types.PendingDeposit do
2+
@moduledoc """
3+
Struct definition for `PendingDeposit`.
4+
Added in Electra fork (EIP7251).
5+
"""
6+
7+
use LambdaEthereumConsensus.Container
8+
9+
fields = [:pubkey, :withdrawal_credentials, :amount, :signature, :slot]
10+
@enforce_keys fields
11+
defstruct fields
12+
13+
@type t :: %__MODULE__{
14+
pubkey: Types.bls_pubkey(),
15+
withdrawal_credentials: Types.bytes32(),
16+
amount: Types.gwei(),
17+
signature: Types.bls_signature(),
18+
slot: Types.slot()
19+
}
20+
21+
@impl LambdaEthereumConsensus.Container
22+
def schema() do
23+
[
24+
{:pubkey, TypeAliases.bls_pubkey()},
25+
{:withdrawal_credentials, TypeAliases.bytes32()},
26+
{:amount, TypeAliases.gwei()},
27+
{:signature, TypeAliases.bls_signature()},
28+
{:slot, TypeAliases.slot()}
29+
]
30+
end
31+
end

0 commit comments

Comments
 (0)