diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index 89075580a..82220d809 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -566,6 +566,7 @@ defmodule LambdaEthereumConsensus.SszEx do defp get_fixed_size(:bool), do: 1 defp get_fixed_size({:int, size}), do: div(size, @bits_per_byte) defp get_fixed_size({:bytes, size}), do: size + defp get_fixed_size({:vector, _, size}), do: size defp get_fixed_size(module) when is_atom(module) do schemas = module.schema() @@ -576,6 +577,7 @@ defmodule LambdaEthereumConsensus.SszEx do end defp variable_size?({:list, _, _}), do: true + defp variable_size?({:vector, _, _}), do: false defp variable_size?(:bool), do: false defp variable_size?({:int, _}), do: false defp variable_size?({:bytes, _}), do: false diff --git a/lib/types/beacon_chain/attestation.ex b/lib/types/beacon_chain/attestation.ex index 7aa959e25..da565156a 100644 --- a/lib/types/beacon_chain/attestation.ex +++ b/lib/types/beacon_chain/attestation.ex @@ -3,6 +3,7 @@ defmodule Types.Attestation do Struct definition for `AttestationMainnet`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :aggregation_bits, @@ -14,9 +15,18 @@ defmodule Types.Attestation do defstruct fields @type t :: %__MODULE__{ - # max validators per committee is 2048 + # MAX_VALIDATORS_PER_COMMITTEE aggregation_bits: Types.bitlist(), data: Types.AttestationData.t(), signature: Types.bls_signature() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:aggregation_bits, {:bitlist, ChainSpec.get("MAX_VALIDATORS_PER_COMMITTEE")}}, + {:data, Types.AttestationData}, + {:signature, TypeAliases.bls_signature()} + ] + end end diff --git a/lib/types/beacon_chain/attestation_data.ex b/lib/types/beacon_chain/attestation_data.ex index df7b80163..cacca8317 100644 --- a/lib/types/beacon_chain/attestation_data.ex +++ b/lib/types/beacon_chain/attestation_data.ex @@ -28,9 +28,9 @@ defmodule Types.AttestationData do @impl LambdaEthereumConsensus.Container def schema do [ - {:slot, {:int, 64}}, - {:index, {:int, 64}}, - {:beacon_block_root, {:bytes, 32}}, + {:slot, TypeAliases.slot()}, + {:index, TypeAliases.commitee_index()}, + {:beacon_block_root, TypeAliases.root()}, {:source, Types.Checkpoint}, {:target, Types.Checkpoint} ] diff --git a/lib/types/beacon_chain/attester_slashing.ex b/lib/types/beacon_chain/attester_slashing.ex index e9b80d9b0..727cc85a2 100644 --- a/lib/types/beacon_chain/attester_slashing.ex +++ b/lib/types/beacon_chain/attester_slashing.ex @@ -3,6 +3,7 @@ defmodule Types.AttesterSlashing do Struct definition for `AttesterSlashing`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :attestation_1, @@ -16,4 +17,12 @@ defmodule Types.AttesterSlashing do attestation_1: Types.IndexedAttestation.t(), attestation_2: Types.IndexedAttestation.t() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:attestation_1, Types.IndexedAttestation}, + {:attestation_2, Types.IndexedAttestation} + ] + end end diff --git a/lib/types/beacon_chain/beacon_block.ex b/lib/types/beacon_chain/beacon_block.ex index d4fdc51d3..fda8e6f6c 100644 --- a/lib/types/beacon_chain/beacon_block.ex +++ b/lib/types/beacon_chain/beacon_block.ex @@ -3,6 +3,7 @@ defmodule Types.BeaconBlock do Struct definition for `BeaconBlock`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :slot, @@ -22,4 +23,15 @@ defmodule Types.BeaconBlock do state_root: Types.root(), body: Types.BeaconBlockBody.t() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:slot, TypeAliases.slot()}, + {:proposer_index, TypeAliases.validator_index()}, + {:parent_root, TypeAliases.root()}, + {:state_root, TypeAliases.root()}, + {:body, Types.BeaconBlockBody} + ] + end end diff --git a/lib/types/beacon_chain/beacon_block_body.ex b/lib/types/beacon_chain/beacon_block_body.ex index a5827e685..f6f041871 100644 --- a/lib/types/beacon_chain/beacon_block_body.ex +++ b/lib/types/beacon_chain/beacon_block_body.ex @@ -3,6 +3,7 @@ defmodule Types.BeaconBlockBody do Struct definition for `BeaconBlockBody`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :randao_reveal, @@ -25,13 +26,40 @@ defmodule Types.BeaconBlockBody do randao_reveal: Types.bls_signature(), eth1_data: Types.Eth1Data.t(), graffiti: Types.bytes32(), + # max MAX_PROPOSER_SLASHINGS proposer_slashings: list(Types.ProposerSlashing.t()), + # max MAX_ATTESTER_SLASHINGS attester_slashings: list(Types.AttesterSlashing.t()), + # max MAX_ATTESTATIONS attestations: list(Types.Attestation.t()), + # max MAX_DEPOSITS deposits: list(Types.Deposit.t()), + # max MAX_VOLUNTARY_EXITS voluntary_exits: list(Types.VoluntaryExit.t()), sync_aggregate: Types.SyncAggregate.t(), execution_payload: Types.ExecutionPayload.t(), + # max MAX_BLS_TO_EXECUTION_CHANGES bls_to_execution_changes: list(Types.BLSToExecutionChange.t()) } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:randao_reveal, TypeAliases.bls_signature()}, + {:eth1_data, Types.Eth1Data}, + {:graffiti, TypeAliases.bytes32()}, + {:proposer_slashings, + {:list, Types.ProposerSlashing, ChainSpec.get("MAX_PROPOSER_SLASHINGS")}}, + {:attester_slashings, + {:list, Types.AttesterSlashing, ChainSpec.get("MAX_ATTESTER_SLASHINGS")}}, + {:attestations, {:list, Types.Attestation, ChainSpec.get("MAX_ATTESTATIONS")}}, + {: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.BLSToExecutionChange, ChainSpec.get("MAX_BLS_TO_EXECUTION_CHANGES")}} + ] + end end diff --git a/lib/types/beacon_chain/beacon_block_header.ex b/lib/types/beacon_chain/beacon_block_header.ex index 32036d90c..16dc4b1f5 100644 --- a/lib/types/beacon_chain/beacon_block_header.ex +++ b/lib/types/beacon_chain/beacon_block_header.ex @@ -3,6 +3,7 @@ defmodule Types.BeaconBlockHeader do Struct definition for `BeaconBlockHeader`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :slot, @@ -22,4 +23,15 @@ defmodule Types.BeaconBlockHeader do state_root: Types.root(), body_root: Types.root() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:slot, TypeAliases.slot()}, + {:proposer_index, TypeAliases.validator_index()}, + {:parent_root, TypeAliases.root()}, + {:state_root, TypeAliases.root()}, + {:body_root, TypeAliases.root()} + ] + end end diff --git a/lib/types/beacon_chain/beacon_state.ex b/lib/types/beacon_chain/beacon_state.ex index d1f0c6c78..22af8d019 100644 --- a/lib/types/beacon_chain/beacon_state.ex +++ b/lib/types/beacon_chain/beacon_state.ex @@ -3,6 +3,8 @@ defmodule Types.BeaconState do Struct definition for `BeaconState`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container + alias LambdaEthereumConsensus.Utils.BitVector fields = [ :genesis_time, @@ -46,32 +48,43 @@ defmodule Types.BeaconState do fork: Types.Fork.t(), # History latest_block_header: Types.BeaconBlockHeader.t(), + # size SLOTS_PER_HISTORICAL_ROOT 8192 block_roots: list(Types.root()), + # size SLOTS_PER_HISTORICAL_ROOT 8192 state_roots: list(Types.root()), # Frozen in Capella, replaced by historical_summaries + # size HISTORICAL_ROOTS_LIMIT 16777216 historical_roots: list(Types.root()), # Eth1 eth1_data: Types.Eth1Data.t(), + # size EPOCHS_PER_ETH1_VOTING_PERIOD (64) * SLOTS_PER_EPOCH (32) = 2048 eth1_data_votes: list(Types.Eth1Data.t()), eth1_deposit_index: Types.uint64(), # Registry + # size VALIDATOR_REGISTRY_LIMIT 1099511627776 validators: Aja.Vector.t(Types.Validator.t()), + # size VALIDATOR_REGISTRY_LIMIT 1099511627776 balances: Aja.Vector.t(Types.gwei()), # Randomness + # size EPOCHS_PER_HISTORICAL_VECTOR 65_536 randao_mixes: list(Types.bytes32()), # Slashings # Per-epoch sums of slashed effective balances + # size EPOCHS_PER_SLASHINGS_VECTOR 8192 slashings: list(Types.gwei()), # Participation + # size VALIDATOR_REGISTRY_LIMIT 1099511627776 previous_epoch_participation: Aja.Vector.t(Types.participation_flags()), + # size VALIDATOR_REGISTRY_LIMIT 1099511627776 current_epoch_participation: Aja.Vector.t(Types.participation_flags()), # Finality - # Bit set for every recent justified epoch - justification_bits: Types.bitvector(), + # Bit set for every recent justified epoch size 4 + justification_bits: BitVector.t(), previous_justified_checkpoint: Types.Checkpoint.t(), current_justified_checkpoint: Types.Checkpoint.t(), finalized_checkpoint: Types.Checkpoint.t(), # Inactivity + # size VALIDATOR_REGISTRY_LIMIT 1099511627776 inactivity_scores: list(Types.uint64()), # Sync current_sync_committee: Types.SyncCommittee.t(), @@ -86,6 +99,7 @@ defmodule Types.BeaconState do next_withdrawal_validator_index: Types.withdrawal_index(), # Deep history valid from Capella onwards # [New in Capella] + # HISTORICAL_ROOTS_LIMIT historical_summaries: list(Types.HistoricalSummary.t()) } @@ -219,4 +233,45 @@ defmodule Types.BeaconState do end end) end + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:genesis_time, TypeAliases.uint64()}, + {:genesis_validators_root, TypeAliases.root()}, + {:slot, TypeAliases.slot()}, + {:fork, Types.Fork}, + {:latest_block_header, Types.BeaconBlockHeader}, + {:block_roots, {:vector, TypeAliases.root(), ChainSpec.get("SLOTS_PER_HISTORICAL_ROOT")}}, + {:state_roots, {:vector, TypeAliases.root(), ChainSpec.get("SLOTS_PER_HISTORICAL_ROOT")}}, + {:historical_roots, {:list, TypeAliases.root(), ChainSpec.get("HISTORICAL_ROOTS_LIMIT")}}, + {:eth1_data, Types.Eth1Data}, + {:eth1_data_votes, + {:list, Types.Eth1Data, + ChainSpec.get("EPOCHS_PER_ETH1_VOTING_PERIOD") * ChainSpec.get("SLOTS_PER_EPOCH")}}, + {:eth1_deposit_index, TypeAliases.uint64()}, + {:validators, {:list, Types.Validator, ChainSpec.get("VALIDATOR_REGISTRY_LIMIT")}}, + {:balances, {:list, TypeAliases.gwei(), ChainSpec.get("VALIDATOR_REGISTRY_LIMIT")}}, + {:randao_mixes, + {:vector, TypeAliases.bytes32(), ChainSpec.get("EPOCHS_PER_HISTORICAL_VECTOR")}}, + {:slashings, {:vector, TypeAliases.gwei(), ChainSpec.get("EPOCHS_PER_SLASHINGS_VECTOR")}}, + {:previous_epoch_participation, + {:list, TypeAliases.participation_flags(), ChainSpec.get("VALIDATOR_REGISTRY_LIMIT")}}, + {:current_epoch_participation, + {:list, TypeAliases.participation_flags(), ChainSpec.get("VALIDATOR_REGISTRY_LIMIT")}}, + {:justification_bits, {:bitvector, ChainSpec.get("JUSTIFICATION_BITS_LENGTH")}}, + {:previous_justified_checkpoint, Types.Checkpoint}, + {:current_justified_checkpoint, Types.Checkpoint}, + {:finalized_checkpoint, Types.Checkpoint}, + {:inactivity_scores, + {:list, TypeAliases.uint64(), ChainSpec.get("VALIDATOR_REGISTRY_LIMIT")}}, + {:current_sync_committee, Types.SyncCommittee}, + {:next_sync_committee, Types.SyncCommittee}, + {:latest_execution_payload_header, Types.ExecutionPayloadHeader}, + {:next_withdrawal_index, TypeAliases.withdrawal_index()}, + {:next_withdrawal_validator_index, TypeAliases.validator_index()}, + {:historical_summaries, + {:list, Types.HistoricalSummary, ChainSpec.get("HISTORICAL_ROOTS_LIMIT")}} + ] + end end diff --git a/lib/types/beacon_chain/bls_to_execution_change.ex b/lib/types/beacon_chain/bls_to_execution_change.ex index 925487ca3..3b21944c7 100644 --- a/lib/types/beacon_chain/bls_to_execution_change.ex +++ b/lib/types/beacon_chain/bls_to_execution_change.ex @@ -3,6 +3,7 @@ defmodule Types.BLSToExecutionChange do Struct definition for `BLSToExecutionChange`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :validator_index, @@ -18,4 +19,13 @@ defmodule Types.BLSToExecutionChange do from_bls_pubkey: Types.bls_pubkey(), to_execution_address: Types.execution_address() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:validator_index, TypeAliases.validator_index()}, + {:from_bls_pubkey, TypeAliases.bls_pubkey()}, + {:to_execution_address, TypeAliases.execution_address()} + ] + end end diff --git a/lib/types/beacon_chain/checkpoint.ex b/lib/types/beacon_chain/checkpoint.ex index 856ea9c06..492bf66e1 100644 --- a/lib/types/beacon_chain/checkpoint.ex +++ b/lib/types/beacon_chain/checkpoint.ex @@ -18,10 +18,11 @@ defmodule Types.Checkpoint do root: Types.root() } + @impl LambdaEthereumConsensus.Container def schema do [ - {:epoch, {:int, 64}}, - {:root, {:bytes, 32}} + {:epoch, TypeAliases.epoch()}, + {:root, TypeAliases.root()} ] end end diff --git a/lib/types/beacon_chain/deposit.ex b/lib/types/beacon_chain/deposit.ex index ef240eee7..c0bb015fb 100644 --- a/lib/types/beacon_chain/deposit.ex +++ b/lib/types/beacon_chain/deposit.ex @@ -3,6 +3,7 @@ defmodule Types.Deposit do Struct definition for `Deposit`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :proof, @@ -40,4 +41,12 @@ defmodule Types.Deposit do slashed: false } end + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:proof, {:vector, TypeAliases.bytes32(), 33}}, + {:data, Types.DepositData} + ] + end end diff --git a/lib/types/beacon_chain/deposit_data.ex b/lib/types/beacon_chain/deposit_data.ex index 86792a44d..0cb632bd6 100644 --- a/lib/types/beacon_chain/deposit_data.ex +++ b/lib/types/beacon_chain/deposit_data.ex @@ -3,6 +3,7 @@ defmodule Types.DepositData do Struct definition for `DepositData`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :pubkey, @@ -18,6 +19,17 @@ defmodule Types.DepositData do pubkey: Types.bls_pubkey(), withdrawal_credentials: Types.bytes32(), amount: Types.gwei(), + # Signing over DepositMessage signature: Types.bls_signature() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:pubkey, TypeAliases.bls_pubkey()}, + {:withdrawal_credentials, TypeAliases.bytes32()}, + {:amount, TypeAliases.gwei()}, + {:signature, TypeAliases.bls_signature()} + ] + end end diff --git a/lib/types/beacon_chain/deposit_message.ex b/lib/types/beacon_chain/deposit_message.ex index d03f01f6f..a0860a080 100644 --- a/lib/types/beacon_chain/deposit_message.ex +++ b/lib/types/beacon_chain/deposit_message.ex @@ -3,6 +3,7 @@ defmodule Types.DepositMessage do Struct definition for `DepositMessage`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :pubkey, @@ -18,4 +19,13 @@ defmodule Types.DepositMessage do withdrawal_credentials: Types.bytes32(), amount: Types.gwei() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:pubkey, TypeAliases.bls_pubkey()}, + {:withdrawal_credentials, TypeAliases.bytes32()}, + {:amount, TypeAliases.gwei()} + ] + end end diff --git a/lib/types/beacon_chain/eth1_data.ex b/lib/types/beacon_chain/eth1_data.ex index 776aed1f1..4042bc637 100644 --- a/lib/types/beacon_chain/eth1_data.ex +++ b/lib/types/beacon_chain/eth1_data.ex @@ -3,6 +3,7 @@ defmodule Types.Eth1Data do Struct definition for `Eth1Data`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :deposit_root, @@ -18,4 +19,13 @@ defmodule Types.Eth1Data do deposit_count: Types.uint64(), block_hash: Types.hash32() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:deposit_root, TypeAliases.root()}, + {:deposit_count, TypeAliases.uint64()}, + {:block_hash, TypeAliases.hash32()} + ] + end end diff --git a/lib/types/beacon_chain/execution_payload.ex b/lib/types/beacon_chain/execution_payload.ex index ec82e9cea..951a0091a 100644 --- a/lib/types/beacon_chain/execution_payload.ex +++ b/lib/types/beacon_chain/execution_payload.ex @@ -3,6 +3,7 @@ defmodule Types.ExecutionPayload do Struct definition for `ExecutionPayload`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :parent_hash, @@ -30,16 +31,20 @@ defmodule Types.ExecutionPayload do fee_recipient: Types.execution_address(), state_root: Types.root(), receipts_root: Types.root(), + # size BYTES_PER_LOGS_BLOOM logs_bloom: binary(), prev_randao: Types.bytes32(), block_number: Types.uint64(), gas_limit: Types.uint64(), gas_used: Types.uint64(), timestamp: Types.uint64(), + # size MAX_EXTRA_DATA_BYTES extra_data: binary(), base_fee_per_gas: Types.uint256(), block_hash: Types.hash32(), + # size MAX_TRANSACTIONS_PER_PAYLOAD transactions: list(Types.transaction()), + # size MAX_TRANSACTIONS_PER_PAYLOAD withdrawals: list(Types.Withdrawal.t()) } @@ -50,4 +55,25 @@ defmodule Types.ExecutionPayload do def decode(%__MODULE__{} = map) do Map.update!(map, :base_fee_per_gas, &Ssz.decode_u256/1) end + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:parent_hash, TypeAliases.hash32()}, + {:fee_recipient, TypeAliases.execution_address()}, + {:state_root, TypeAliases.root()}, + {:receipts_root, TypeAliases.root()}, + {:logs_bloom, {:vector, {:int, 8}, ChainSpec.get("BYTES_PER_LOGS_BLOOM")}}, + {:prev_randao, TypeAliases.bytes32()}, + {:block_number, TypeAliases.uint64()}, + {:gas_limit, TypeAliases.uint64()}, + {:gas_used, TypeAliases.uint64()}, + {:timestamp, TypeAliases.uint64()}, + {:extra_data, TypeAliases.byte_list(ChainSpec.get("MAX_EXTRA_DATA_BYTES"))}, + {:base_fee_per_gas, TypeAliases.uint256()}, + {:block_hash, TypeAliases.hash32()}, + {:transactions, TypeAliases.transaction()}, + {:withdrawals, {:list, Types.Withdrawal, ChainSpec.get("MAX_TRANSACTIONS_PER_PAYLOAD")}} + ] + end end diff --git a/lib/types/beacon_chain/execution_payload_header.ex b/lib/types/beacon_chain/execution_payload_header.ex index b685d50f4..007d2d96f 100644 --- a/lib/types/beacon_chain/execution_payload_header.ex +++ b/lib/types/beacon_chain/execution_payload_header.ex @@ -3,6 +3,7 @@ defmodule Types.ExecutionPayloadHeader do Struct definition for `ExecutionPayloadHeader`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container @default_execution_payload_header %{ parent_hash: <<0::256>>, @@ -48,13 +49,15 @@ defmodule Types.ExecutionPayloadHeader do fee_recipient: Types.execution_address(), state_root: Types.root(), receipts_root: Types.root(), - logs_bloom: binary(), + # size BYTES_PER_LOGS_BLOOM 256 + logs_bloom: list(Types.uint8()), prev_randao: Types.bytes32(), block_number: Types.uint64(), gas_limit: Types.uint64(), gas_used: Types.uint64(), timestamp: Types.uint64(), - extra_data: binary(), + # size MAX_EXTRA_DATA_BYTES 32 + extra_data: list(Types.bytes1()), base_fee_per_gas: Types.uint256(), block_hash: Types.hash32(), transactions_root: Types.root(), @@ -72,4 +75,25 @@ defmodule Types.ExecutionPayloadHeader do def default do @default_execution_payload_header end + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:parent_hash, TypeAliases.hash32()}, + {:fee_recipient, TypeAliases.execution_address()}, + {:state_root, TypeAliases.root()}, + {:receipts_root, TypeAliases.root()}, + {:logs_bloom, {:vector, {:int, 8}, ChainSpec.get("BYTES_PER_LOGS_BLOOM")}}, + {:prev_randao, TypeAliases.bytes32()}, + {:block_number, TypeAliases.uint64()}, + {:gas_limit, TypeAliases.uint64()}, + {:gas_used, TypeAliases.uint64()}, + {:timestamp, TypeAliases.uint64()}, + {:extra_data, TypeAliases.byte_list(ChainSpec.get("MAX_EXTRA_DATA_BYTES"))}, + {:base_fee_per_gas, TypeAliases.uint256()}, + {:block_hash, TypeAliases.hash32()}, + {:transactions_root, TypeAliases.root()}, + {:withdrawals_root, TypeAliases.root()} + ] + end end diff --git a/lib/types/beacon_chain/fork.ex b/lib/types/beacon_chain/fork.ex index ae57b09d0..2aed895c9 100644 --- a/lib/types/beacon_chain/fork.ex +++ b/lib/types/beacon_chain/fork.ex @@ -4,6 +4,8 @@ defmodule Types.Fork do Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container + fields = [ :previous_version, :current_version, @@ -18,4 +20,13 @@ defmodule Types.Fork do current_version: Types.version(), epoch: Types.epoch() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:previous_version, TypeAliases.version()}, + {:current_version, TypeAliases.version()}, + {:epoch, TypeAliases.epoch()} + ] + end end diff --git a/lib/types/beacon_chain/fork_data.ex b/lib/types/beacon_chain/fork_data.ex index a9ef1b733..371288492 100644 --- a/lib/types/beacon_chain/fork_data.ex +++ b/lib/types/beacon_chain/fork_data.ex @@ -4,6 +4,8 @@ defmodule Types.ForkData do Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container + fields = [ :current_version, :genesis_validators_root @@ -16,4 +18,12 @@ defmodule Types.ForkData do current_version: Types.version(), genesis_validators_root: Types.root() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:current_version, TypeAliases.version()}, + {:genesis_validators_root, TypeAliases.root()} + ] + end end diff --git a/lib/types/beacon_chain/historical_batch.ex b/lib/types/beacon_chain/historical_batch.ex index a9bcbde55..f022879d5 100644 --- a/lib/types/beacon_chain/historical_batch.ex +++ b/lib/types/beacon_chain/historical_batch.ex @@ -3,6 +3,7 @@ defmodule Types.HistoricalBatch do Struct definition for `HistoricalBatch`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :block_roots, @@ -13,7 +14,16 @@ defmodule Types.HistoricalBatch do defstruct fields @type t :: %__MODULE__{ + # size SLOTS_PER_HISTORICAL_ROOT 8192 block_roots: list(Types.root()), state_roots: list(Types.root()) } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:block_roots, {:vector, TypeAliases.root(), ChainSpec.get("SLOTS_PER_HISTORICAL_ROOT")}}, + {:state_roots, {:vector, TypeAliases.root(), ChainSpec.get("SLOTS_PER_HISTORICAL_ROOT")}} + ] + end end diff --git a/lib/types/beacon_chain/historical_summary.ex b/lib/types/beacon_chain/historical_summary.ex index 0c5482474..89350086d 100644 --- a/lib/types/beacon_chain/historical_summary.ex +++ b/lib/types/beacon_chain/historical_summary.ex @@ -2,7 +2,10 @@ defmodule Types.HistoricalSummary do @moduledoc """ Struct definition for `HistoricalSummary`. Related definitions in `native/ssz_nif/src/types/`. + `HistoricalSummary` matches the components of the phase0 `HistoricalBatch` + making the two hash_tree_root-compatible. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :block_summary_root, @@ -16,4 +19,12 @@ defmodule Types.HistoricalSummary do block_summary_root: Types.root(), state_summary_root: Types.root() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:block_summary_root, TypeAliases.root()}, + {:state_summary_root, TypeAliases.root()} + ] + end end diff --git a/lib/types/beacon_chain/indexed_attestation.ex b/lib/types/beacon_chain/indexed_attestation.ex index 0a693f5da..4a1566d2d 100644 --- a/lib/types/beacon_chain/indexed_attestation.ex +++ b/lib/types/beacon_chain/indexed_attestation.ex @@ -15,7 +15,7 @@ defmodule Types.IndexedAttestation do defstruct fields @type t :: %__MODULE__{ - # max size is 2048 + # max size is MAX_VALIDATORS_PER_COMMITTEE attesting_indices: list(Types.validator_index()), data: Types.AttestationData.t(), signature: Types.bls_signature() @@ -24,9 +24,10 @@ defmodule Types.IndexedAttestation do @impl LambdaEthereumConsensus.Container def schema do [ - {:attesting_indices, {:list, {:int, 64}, 2048}}, + {:attesting_indices, + {:list, TypeAliases.validator_index(), ChainSpec.get("MAX_VALIDATORS_PER_COMMITTEE")}}, {:data, Types.AttestationData}, - {:signature, {:bytes, 96}} + {:signature, TypeAliases.bls_signature()} ] end end diff --git a/lib/types/beacon_chain/pending_attestation.ex b/lib/types/beacon_chain/pending_attestation.ex index d912c759c..d04d22815 100644 --- a/lib/types/beacon_chain/pending_attestation.ex +++ b/lib/types/beacon_chain/pending_attestation.ex @@ -3,6 +3,7 @@ defmodule Types.PendingAttestation do Struct definition for `PendingAttestation`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :aggregation_bits, @@ -15,9 +16,20 @@ defmodule Types.PendingAttestation do defstruct fields @type t :: %__MODULE__{ + # max size is MAX_VALIDATORS_PER_COMMITTEE aggregation_bits: Types.bitlist(), data: Types.AttestationData.t(), inclusion_delay: Types.slot(), proposer_index: Types.validator_index() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:aggregation_bits, {:bitlist, ChainSpec.get("MAX_VALIDATORS_PER_COMMITTEE")}}, + {:data, Types.AttestationData}, + {:inclusion_delay, TypeAliases.slot()}, + {:proposer_index, TypeAliases.validator_index()} + ] + end end diff --git a/lib/types/beacon_chain/proposer_slashing.ex b/lib/types/beacon_chain/proposer_slashing.ex index 6bfaa6115..fd40e3375 100644 --- a/lib/types/beacon_chain/proposer_slashing.ex +++ b/lib/types/beacon_chain/proposer_slashing.ex @@ -3,6 +3,7 @@ defmodule Types.ProposerSlashing do Struct definition for `ProposerSlashing`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :signed_header_1, @@ -16,4 +17,12 @@ defmodule Types.ProposerSlashing do signed_header_1: Types.SignedBeaconBlockHeader.t(), signed_header_2: Types.SignedBeaconBlockHeader.t() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:signed_header_1, Types.SignedBeaconBlockHeader}, + {:signed_header_2, Types.SignedBeaconBlockHeader} + ] + end end diff --git a/lib/types/beacon_chain/signed_beacon_block.ex b/lib/types/beacon_chain/signed_beacon_block.ex index f1bb692c1..938e340fb 100644 --- a/lib/types/beacon_chain/signed_beacon_block.ex +++ b/lib/types/beacon_chain/signed_beacon_block.ex @@ -3,6 +3,7 @@ defmodule Types.SignedBeaconBlock do Struct definition for `SignedBeaconBlock`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :message, @@ -16,4 +17,12 @@ defmodule Types.SignedBeaconBlock do message: Types.BeaconBlock.t(), signature: Types.bls_signature() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:message, Types.BeaconBlock}, + {:signature, TypeAliases.bls_signature()} + ] + end end diff --git a/lib/types/beacon_chain/signed_beacon_block_header.ex b/lib/types/beacon_chain/signed_beacon_block_header.ex index ca100c248..a1b8c6a92 100644 --- a/lib/types/beacon_chain/signed_beacon_block_header.ex +++ b/lib/types/beacon_chain/signed_beacon_block_header.ex @@ -3,6 +3,7 @@ defmodule Types.SignedBeaconBlockHeader do Struct definition for `SignedBeaconBlockHeader`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :message, @@ -16,4 +17,12 @@ defmodule Types.SignedBeaconBlockHeader do message: Types.BeaconBlockHeader.t(), signature: Types.bls_signature() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:message, Types.BeaconBlockHeader}, + {:signature, TypeAliases.bls_signature()} + ] + end end diff --git a/lib/types/beacon_chain/signed_bls_to_execution_change.ex b/lib/types/beacon_chain/signed_bls_to_execution_change.ex index 75048c564..a31efc8ba 100644 --- a/lib/types/beacon_chain/signed_bls_to_execution_change.ex +++ b/lib/types/beacon_chain/signed_bls_to_execution_change.ex @@ -3,6 +3,7 @@ defmodule Types.SignedBLSToExecutionChange do Struct definition for `SignedBLSToExecutionChange`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :message, @@ -16,4 +17,12 @@ defmodule Types.SignedBLSToExecutionChange do message: Types.BLSToExecutionChange.t(), signature: Types.bls_signature() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:message, Types.BLSToExecutionChange}, + {:signature, TypeAliases.bls_signature()} + ] + end end diff --git a/lib/types/beacon_chain/signed_voluntary_exit.ex b/lib/types/beacon_chain/signed_voluntary_exit.ex index 24070182d..56ade50ce 100644 --- a/lib/types/beacon_chain/signed_voluntary_exit.ex +++ b/lib/types/beacon_chain/signed_voluntary_exit.ex @@ -3,6 +3,7 @@ defmodule Types.SignedVoluntaryExit do Struct definition for `SignedVoluntaryExit`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :message, @@ -16,4 +17,12 @@ defmodule Types.SignedVoluntaryExit do message: Types.VoluntaryExit.t(), signature: Types.bls_signature() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:message, Types.VoluntaryExit}, + {:signature, TypeAliases.bls_signature()} + ] + end end diff --git a/lib/types/beacon_chain/signing_data.ex b/lib/types/beacon_chain/signing_data.ex index 2637ed17d..880f24d83 100644 --- a/lib/types/beacon_chain/signing_data.ex +++ b/lib/types/beacon_chain/signing_data.ex @@ -3,6 +3,7 @@ defmodule Types.SigningData do Struct definition for `SigningData`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :object_root, @@ -16,4 +17,12 @@ defmodule Types.SigningData do object_root: Types.root(), domain: Types.domain() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:object_root, TypeAliases.root()}, + {:domain, TypeAliases.domain()} + ] + end end diff --git a/lib/types/beacon_chain/sync_aggregate.ex b/lib/types/beacon_chain/sync_aggregate.ex index 491c1f653..38240ae6a 100644 --- a/lib/types/beacon_chain/sync_aggregate.ex +++ b/lib/types/beacon_chain/sync_aggregate.ex @@ -3,6 +3,7 @@ defmodule Types.SyncAggregate do Struct definition for `SyncAggregate`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :sync_committee_bits, @@ -13,7 +14,16 @@ defmodule Types.SyncAggregate do defstruct fields @type t :: %__MODULE__{ + # max size SYNC_COMMITTEE_SIZE sync_committee_bits: Types.bitvector(), sync_committee_signature: Types.bls_signature() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:sync_committee_bits, {:bitvector, ChainSpec.get("SYNC_COMMITTEE_SIZE")}}, + {:sync_committee_signature, TypeAliases.bls_signature()} + ] + end end diff --git a/lib/types/beacon_chain/sync_committee.ex b/lib/types/beacon_chain/sync_committee.ex index 855539851..d7318343e 100644 --- a/lib/types/beacon_chain/sync_committee.ex +++ b/lib/types/beacon_chain/sync_committee.ex @@ -15,6 +15,7 @@ defmodule Types.SyncCommittee do defstruct fields @type t :: %__MODULE__{ + # max size SYNC_COMMITTEE_SIZE pubkeys: list(Types.bls_pubkey()), aggregate_pubkey: Types.bls_pubkey() } @@ -22,8 +23,8 @@ defmodule Types.SyncCommittee do @impl LambdaEthereumConsensus.Container def schema do [ - {:pubkeys, {:list, {:bytes, 48}, 100}}, - {:aggregate_pubkey, {:bytes, 48}} + {:pubkeys, {:vector, TypeAliases.bls_pubkey(), ChainSpec.get("SYNC_COMMITTEE_SIZE")}}, + {:aggregate_pubkey, TypeAliases.bls_pubkey()} ] end end diff --git a/lib/types/beacon_chain/validator.ex b/lib/types/beacon_chain/validator.ex index 9b81b0f5b..8052931a2 100644 --- a/lib/types/beacon_chain/validator.ex +++ b/lib/types/beacon_chain/validator.ex @@ -71,14 +71,14 @@ defmodule Types.Validator do @impl LambdaEthereumConsensus.Container def schema do [ - {:pubkey, {:bytes, 48}}, - {:withdrawal_credentials, {:bytes, 32}}, - {:effective_balance, {:int, 64}}, + {:pubkey, TypeAliases.bls_pubkey()}, + {:withdrawal_credentials, TypeAliases.bytes32()}, + {:effective_balance, TypeAliases.gwei()}, {:slashed, :bool}, - {:activation_eligibility_epoch, {:int, 64}}, - {:activation_epoch, {:int, 64}}, - {:exit_epoch, {:int, 64}}, - {:withdrawable_epoch, {:int, 64}} + {:activation_eligibility_epoch, TypeAliases.epoch()}, + {:activation_epoch, TypeAliases.epoch()}, + {:exit_epoch, TypeAliases.epoch()}, + {:withdrawable_epoch, TypeAliases.epoch()} ] end end diff --git a/lib/types/beacon_chain/voluntary_exit.ex b/lib/types/beacon_chain/voluntary_exit.ex index 3107140fc..9061a4017 100644 --- a/lib/types/beacon_chain/voluntary_exit.ex +++ b/lib/types/beacon_chain/voluntary_exit.ex @@ -3,6 +3,7 @@ defmodule Types.VoluntaryExit do Struct definition for `VoluntaryExit`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :epoch, @@ -16,4 +17,12 @@ defmodule Types.VoluntaryExit do epoch: Types.epoch(), validator_index: Types.validator_index() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:epoch, TypeAliases.epoch()}, + {:validator_index, TypeAliases.validator_index()} + ] + end end diff --git a/lib/types/beacon_chain/withdrawal.ex b/lib/types/beacon_chain/withdrawal.ex index 9dac14bea..b3baca452 100644 --- a/lib/types/beacon_chain/withdrawal.ex +++ b/lib/types/beacon_chain/withdrawal.ex @@ -3,6 +3,7 @@ defmodule Types.Withdrawal do Struct definition for `Withdrawal`. Related definitions in `native/ssz_nif/src/types/`. """ + @behaviour LambdaEthereumConsensus.Container fields = [ :index, @@ -17,7 +18,17 @@ defmodule Types.Withdrawal do @type t :: %__MODULE__{ index: Types.withdrawal_index(), validator_index: Types.validator_index(), - address: Types.hash32(), + address: Types.execution_address(), amount: Types.gwei() } + + @impl LambdaEthereumConsensus.Container + def schema do + [ + {:index, TypeAliases.withdrawal_index()}, + {:validator_index, TypeAliases.validator_index()}, + {:address, TypeAliases.execution_address()}, + {:amount, TypeAliases.gwei()} + ] + end end diff --git a/lib/types/type_aliases.ex b/lib/types/type_aliases.ex new file mode 100644 index 000000000..13d17cbcf --- /dev/null +++ b/lib/types/type_aliases.ex @@ -0,0 +1,28 @@ +defmodule TypeAliases do + @moduledoc """ + Type aliases for ssz schemas + """ + + def root, do: {:bytes, 32} + def epoch, do: {:int, 64} + def bls_signature, do: {:bytes, 96} + def slot, do: {:int, 64} + def commitee_index, do: {:int, 64} + def validator_index, do: {:int, 64} + def gwei, do: {:int, 64} + def participation_flags, do: {:int, 8} + def withdrawal_index, do: {:int, 64} + def bls_pubkey, do: {:bytes, 48} + def execution_address, do: {:bytes, 20} + def version, do: {:bytes, 4} + def domain, do: {:bytes, 32} + def bytes32, do: {:bytes, 32} + def uint64, do: {:int, 64} + def hash32, do: {:bytes, 32} + def uint256, do: {:int, 256} + def transaction, do: byte_list(ChainSpec.get("MAX_BYTES_PER_TRANSACTION")) + def domain_type, do: {:bytes, 4} + def fork_digest, do: {:bytes, 4} + + def byte_list(n), do: {:list, {:int, 8}, n} +end diff --git a/test/unit/ssz_ex_test.exs b/test/unit/ssz_ex_test.exs index 2f9c5fec3..35d1344ae 100644 --- a/test/unit/ssz_ex_test.exs +++ b/test/unit/ssz_ex_test.exs @@ -294,47 +294,6 @@ defmodule Unit.SSZExTest do assert_roundtrip(serialized, validator, Types.Validator) end - test "serialize and deserialize variable container" do - pubkey1 = - <<166, 144, 240, 158, 185, 117, 206, 31, 49, 45, 247, 53, 183, 95, 32, 20, 57, 245, 54, 60, - 97, 78, 24, 81, 227, 157, 191, 150, 163, 202, 1, 72, 46, 131, 80, 54, 55, 203, 11, 160, - 206, 88, 144, 58, 231, 142, 94, 235>> - - pubkey2 = - <<180, 144, 240, 158, 185, 117, 206, 31, 49, 45, 247, 53, 183, 95, 32, 20, 57, 245, 54, 60, - 97, 78, 24, 81, 227, 157, 191, 150, 163, 202, 1, 72, 46, 131, 80, 54, 55, 203, 11, 160, - 206, 88, 144, 58, 231, 142, 94, 235>> - - pubkey3 = - <<190, 144, 240, 158, 185, 117, 206, 31, 49, 45, 247, 53, 183, 95, 32, 20, 57, 245, 54, 60, - 97, 78, 24, 81, 227, 157, 191, 150, 163, 202, 1, 72, 46, 131, 80, 54, 55, 203, 11, 160, - 206, 88, 144, 58, 231, 142, 94, 235>> - - pubkey4 = - <<200, 144, 240, 158, 185, 117, 206, 31, 49, 45, 247, 53, 183, 95, 32, 20, 57, 245, 54, 60, - 97, 78, 24, 81, 227, 157, 191, 150, 163, 202, 1, 72, 46, 131, 80, 54, 55, 203, 11, 160, - 206, 88, 144, 58, 231, 142, 94, 235>> - - sync = %Types.SyncCommittee{ - pubkeys: [pubkey1, pubkey2, pubkey3], - aggregate_pubkey: pubkey4 - } - - serialized = - <<52, 0, 0, 0, 200, 144, 240, 158, 185, 117, 206, 31, 49, 45, 247, 53, 183, 95, 32, 20, 57, - 245, 54, 60, 97, 78, 24, 81, 227, 157, 191, 150, 163, 202, 1, 72, 46, 131, 80, 54, 55, - 203, 11, 160, 206, 88, 144, 58, 231, 142, 94, 235, 166, 144, 240, 158, 185, 117, 206, 31, - 49, 45, 247, 53, 183, 95, 32, 20, 57, 245, 54, 60, 97, 78, 24, 81, 227, 157, 191, 150, - 163, 202, 1, 72, 46, 131, 80, 54, 55, 203, 11, 160, 206, 88, 144, 58, 231, 142, 94, 235, - 180, 144, 240, 158, 185, 117, 206, 31, 49, 45, 247, 53, 183, 95, 32, 20, 57, 245, 54, 60, - 97, 78, 24, 81, 227, 157, 191, 150, 163, 202, 1, 72, 46, 131, 80, 54, 55, 203, 11, 160, - 206, 88, 144, 58, 231, 142, 94, 235, 190, 144, 240, 158, 185, 117, 206, 31, 49, 45, 247, - 53, 183, 95, 32, 20, 57, 245, 54, 60, 97, 78, 24, 81, 227, 157, 191, 150, 163, 202, 1, 72, - 46, 131, 80, 54, 55, 203, 11, 160, 206, 88, 144, 58, 231, 142, 94, 235>> - - assert_roundtrip(serialized, sync, Types.SyncCommittee) - end - test "serialize and deserialize bitlist" do encoded_bytes = <<160, 92, 1>> assert {:ok, decoded_bytes} = SszEx.decode(encoded_bytes, {:bitlist, 16})