Files
Abhishek Krishna a3b7db1874 vms/txs/mempool: add AdmissionVerifier hook for encrypted-payload txs (#115)
Closes luxfi/node#115 by landing the admission-hook half of the issue.
The hook is the substrate the encrypted-mempool partition will use to
admit FHE-ciphertext transactions on (signature + fee + NIZK) without
decryption per LP-066 / luxfi/precompile/fhe.

Surface added:

  type AdmissionVerifier[T Tx] interface {
      VerifyAdmit(tx T) error
  }

  var ErrAdmissionRejected = errors.New("tx admission rejected")

  func NewWithAdmissionVerifier[T Tx](
      metrics Metrics,
      verifier AdmissionVerifier[T],
  ) *mempool[T]

  // New is now a thin wrapper around NewWithAdmissionVerifier(metrics, nil).
  // No behavioral change for existing callers.

Add() invokes verifier.VerifyAdmit last, after duplicate / size / space /
conflict have all passed. Ordering rationale: cheap rejects fire first,
so NIZK verification cost is only paid on a tx that passes structural
admission. A non-nil verifier return is wrapped in ErrAdmissionRejected,
records the drop reason via the existing droppedTxIDs LRU, and never
inserts the tx.

What this does NOT do:
  - It does not define the encrypted-payload tx type or its NIZK proof
    format. Those live in vms/platformvm/txs (or wherever the consumer
    decides) and ship in a follow-up.
  - It does not wire the FHE precompile's bootstrap-meter consultation —
    callers implementing AdmissionVerifier do that themselves.
  - It does not add the per-account FIFO partition for encrypted txs.
    The existing unissuedTxs Hashmap is per-mempool; the partition is
    a separate construction over multiple mempool instances and is a
    follow-up.

What it DOES do: lands the only mempool-side hook the issue requires
without locking us in on the encrypted-tx representation. The hook is
generic (`AdmissionVerifier[T Tx]`) so any future Tx variant can plug
in the same way.

Tests (CGO_ENABLED=0 go test -run TestAdmissionVerifier ./vms/txs/mempool/...
all pass):
  - nil verifier matches New (byte-identical behavior)
  - verifier returning nil admits the tx; gate fires exactly once on
    Add and not on Get / Peek / Iterate / Remove
  - verifier returning an error rejects with ErrAdmissionRejected
    wrapping the verifier's reason; drop reason recorded
  - cheap checks short-circuit before the gate runs (duplicate /
    oversize / conflict all skip the gate)

Refs:
  - issue #115 (this repo)
  - LP-066 (F-Chain confidential compute)
  - LP-183 (ZAP envelope decode precompile; downstream consumer once
    encrypted-payload tx propagation through gossip lands)
  - luxfi/threshold issue #20 (real distributed FHE decryption; the
    block-proposer-side counterpart to this admission-side hook)
2026-06-01 22:32:59 +05:30
..