defmodule KzgElixir do @moduledoc """ Ethereum EIP-4844 KZG trusted setup verification NIF bindings. This module provides NIF bindings to `c-kzg-4844` for verifying KZG proofs, implementing the cryptographic primitives required for EIP-4844 (Proto-Danksharding). """ @on_load :load_nif @type blob :: binary() @type commitment :: binary() @type proof :: binary() @type field_element :: binary() @type cell :: binary() @doc false def load_nif do path = :code.priv_dir(:kzg_elixir) :erlang.load_nif(Path.join(path, "kzg_nif"), 0) end @doc """ Loads the KZG trusted setup from a file. ## Arguments * `file`: Path to the trusted setup configuration file from `c-kzg-4844`. ## Returns * `:ok` on success. * `{:error, reason}` on failure (e.g., file not found, bad format). """ @spec load_trusted_setup(String.t()) :: :ok | {:error, term()} def load_trusted_setup(_file), do: :erlang.nif_error(:nif_not_loaded) @doc """ Computes the KZG commitment for a given blob. ## Arguments * `blob`: The data blob (4096 field elements, 131072 bytes). ## Returns * `{:ok, commitment}`: The 48-byte KZG commitment. * `{:error, reason}`: If computation fails. """ @spec blob_to_kzg_commitment(blob()) :: {:ok, commitment()} | {:error, term()} def blob_to_kzg_commitment(_blob), do: :erlang.nif_error(:nif_not_loaded) @doc """ Computes a KZG proof for a blob at a given evaluation point `z`. ## Arguments * `blob`: The data blob. * `z`: The evaluation point (32 bytes). ## Returns * `{:ok, {proof, y}}`: Tuple containing the 48-byte proof and the evaluation result `y`. * `{:error, reason}`: If computation fails. """ @spec compute_kzg_proof(blob(), field_element()) :: {:ok, {proof(), field_element()}} | {:error, term()} def compute_kzg_proof(_blob, _z), do: :erlang.nif_error(:nif_not_loaded) @doc """ Verifies a KZG proof. ## Arguments * `commitment`: The 48-byte KZG commitment. * `z`: The evaluation point (32 bytes). * `y`: The evaluation result (32 bytes). * `proof`: The 48-byte proof. ## Returns * `{:ok, true}` if valid. * `{:ok, false}` if invalid. * `{:error, reason}` on error. """ @spec verify_kzg_proof(commitment(), field_element(), field_element(), proof()) :: {:ok, boolean()} | {:error, term()} def verify_kzg_proof(_commitment, _z, _y, _proof), do: :erlang.nif_error(:nif_not_loaded) @doc """ Verifies a KZG proof for a blob. ## Arguments * `blob`: The data blob. * `commitment`: The 48-byte KZG commitment. * `proof`: The 48-byte proof. ## Returns * `{:ok, true}` if valid. * `{:ok, false}` if invalid. * `{:error, reason}` on error. """ @spec verify_blob_kzg_proof(blob(), commitment(), proof()) :: {:ok, boolean()} | {:error, term()} def verify_blob_kzg_proof(_blob, _commitment, _proof), do: :erlang.nif_error(:nif_not_loaded) @doc """ Computes a blob KZG proof for a given blob and commitment. This matches `c-kzg-4844`'s `compute_blob_kzg_proof`. ## Returns * `{:ok, proof}` on success. * `{:error, reason}` on failure. """ @spec compute_blob_kzg_proof(blob(), commitment()) :: {:ok, proof()} | {:error, term()} def compute_blob_kzg_proof(_blob, _commitment), do: :erlang.nif_error(:nif_not_loaded) @doc """ Verifies a batch of blob KZG proofs. This matches `c-kzg-4844`'s `verify_blob_kzg_proof_batch`. ## Returns * `{:ok, true}` if the batch is valid. * `{:ok, false}` if the batch is invalid. * `{:error, reason}` on error. """ @spec verify_blob_kzg_proof_batch([blob()], [commitment()], [proof()]) :: {:ok, boolean()} | {:error, term()} def verify_blob_kzg_proof_batch(_blobs, _commitments, _proofs), do: :erlang.nif_error(:nif_not_loaded) @doc """ Computes the Fiat–Shamir challenge used in blob verification. This wraps the internal `c-kzg-4844` helper `compute_challenge`. """ @spec compute_challenge(blob(), commitment()) :: {:ok, field_element()} | {:error, term()} def compute_challenge(_blob, _commitment), do: :erlang.nif_error(:nif_not_loaded) @doc """ EIP-7594: Compute cells and corresponding KZG proofs for a blob. """ @spec compute_cells_and_kzg_proofs(blob()) :: {:ok, {list(cell()), list(proof())}} | {:error, term()} def compute_cells_and_kzg_proofs(_blob), do: :erlang.nif_error(:nif_not_loaded) @doc """ EIP-7594: Recover missing cells and proofs given a partial set. """ @spec recover_cells_and_kzg_proofs([non_neg_integer()], list(cell())) :: {:ok, {list(cell()), list(proof())}} | {:error, term()} def recover_cells_and_kzg_proofs(_cell_indices, _cells), do: :erlang.nif_error(:nif_not_loaded) @doc """ EIP-7594: Verify a batch of cell KZG proofs. """ @spec verify_cell_kzg_proof_batch([commitment()], [non_neg_integer()], list(cell()), [proof()]) :: {:ok, boolean()} | {:error, term()} def verify_cell_kzg_proof_batch(_commitments, _cell_indices, _cells, _proofs), do: :erlang.nif_error(:nif_not_loaded) @doc """ EIP-7594: Compute the challenge used by `verify_cell_kzg_proof_batch`. Exposed for test vectors. """ @spec compute_verify_cell_kzg_proof_batch_challenge( [commitment()], [non_neg_integer()], [non_neg_integer()], list(cell()), [proof()] ) :: {:ok, field_element()} | {:error, term()} def compute_verify_cell_kzg_proof_batch_challenge( _commitments, _commitment_indices, _cell_indices, _cells, _proofs ), do: :erlang.nif_error(:nif_not_loaded) end