defmodule Types.BeaconBlockBody do
  @moduledoc """
  Struct definition for `BeaconBlockBody`.
  Related definitions in `native/ssz_nif/src/types/`.
  """
  use LambdaEthereumConsensus.Container

  fields = [
    :randao_reveal,
    :eth1_data,
    :graffiti,
    :proposer_slashings,
    :attester_slashings,
    :attestations,
    :deposits,
    :voluntary_exits,
    :sync_aggregate,
    :execution_payload,
    :bls_to_execution_changes,
    :blob_kzg_commitments,
    # New Electra fields
    :execution_requests
  ]

  @enforce_keys fields
  defstruct fields

  @type t :: %__MODULE__{
          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.SignedVoluntaryExit.t()),
          sync_aggregate: Types.SyncAggregate.t(),
          execution_payload: Types.ExecutionPayload.t(),
          # 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()),
          # New in Electra
          execution_requests: Types.ExecutionRequests.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")},
      # [Modified in Electra:EIP7549]
      attester_slashings:
        {: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")},
      # New in Electra
      execution_requests: Types.ExecutionRequests
    ]
  end
end
