Files
hips/HIPs/hip-0087-pq-permit.md
zeekayandHanzo Dev 7a9dcac628 What each runtime implements of the Hanzo corpus
An audit read the code and found the proposal that specifies it. Go reaches
all 122 capability proposals and 64 of the 121 other Standards Track ones;
Rust has 35, mostly the operator and the CLI; C++ has three, because the
complete original C++ in the estate is a ZAP handler, a bot nothing specifies,
and authored kernels inside forked CUDA and Metal crates.

    | | shipped | partial | none | not assessed |
    | Go   | 146 | 33 | 1 |  80 |
    | C++  |   1 |  2 | 0 | 257 |
    | Rust |  10 | 25 | 1 | 224 |

The large "not assessed" columns are the point rather than a gap. The model and
training specs are Python, the frontend and design-system proposals are
TypeScript, and recording `none` against those would read as a search that
came up empty when the honest statement is that the runtime was never the
question. Governance, Meta and Process are not graded at all.

Six proposals are Final with nothing found in Go and are left unwritten rather
than demoted: 0065, 0089, 0098, 0103, 0521 and 0902. HIP-0521 answers itself,
its own section reading "Not yet implemented". Three of the others name a
canonical Go file in consensus/protocol/auth that nobody wrote, in a package
where the four neighbouring proposals' files all exist with tests beside them.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-05 19:18:13 -07:00

3.8 KiB

hip, title, type, category, status, implementation-go, author, created, requires
hip title type category status implementation-go author created requires
0087 PQ Permit (replaces EIP-2612) Standards Track Cryptography Final shipped Hanzo AI 2026-05-11 HIP-0005, HIP-0077, HIP-0085, HIP-0086

HIP-0087: PQ Permit (replaces EIP-2612)

Abstract

HIP-0087 specifies the post-quantum replacement for EIP-2612 permit. A PQ Permit is a typed off-chain authorization signed by the token owner's ML-DSA-65 key over a TupleHash256 transcript bound by the cust string PERMIT-V1 (SP 800-185). The transcript commits to (profile_id, chain_id, verifying_contract, owner_account_id, spender_account_id, value, nonce, deadline). A contract verifies the permit via the Z-Chain auth precompile (HIP-0104) or directly via the ML-DSA.Verify precompile. The replay protection follows EIP-2612's per-owner nonce pattern. The whole flow is profile-gated; a strict-PQ chain refuses any classical permit.

Specification

Canonical reference: luxfi/consensus/protocol/auth/permit.go (auth-pq-surface branch).

PermitMessage {
    version              uint8    = 0x01
    profile_id           uint8
    identity_scheme_id   uint8    = 0x42
    hash_suite_id        uint8    = 0x01
    chain_id             uint64
    verifying_contract   [20]byte // EVM-form
    owner_account_id     [48]byte
    spender_account_id   [48]byte
    value                [32]byte // u256 big-endian
    nonce                uint64
    deadline             uint64
}

transcript = TupleHash256(
    "PERMIT-V1",
    [ version, profile_id, identity_scheme_id, hash_suite_id,
      chain_id_be8, verifying_contract, owner_account_id,
      spender_account_id, value, nonce_be8, deadline_be8 ],
    384
)

signature = ML-DSA.Sign(owner_account_key, transcript)

The owner publishes (PermitMessage, owner_pubkey, signature). The contract calls a thin verifier (either the Z-Chain proof precompile in HIP-0104 or a direct ML-DSA.Verify precompile at address 0x14) and on success increments the owner's nonce and updates allowance[owner][spender] = value.

Acceptance:

  1. profile_id matches chain pin; otherwise reject.
  2. chain_id matches.
  3. verifying_contract == msg.sender.
  4. now <= deadline.
  5. nonce == nonces[owner].
  6. AccountID == cSHAKE256(profile_be4 || chain_be4 || u8(scheme) || owner_pubkey, 48, "", "LUX_ACCOUNT_ID_V1"), per HIP-0085.
  7. ML-DSA.Verify(owner_pubkey, transcript, signature) == true.

Failure of any check is a hard revert; no recovery.

Backwards compatibility

None. EIP-2612 permits are refused under strict-PQ. Token contracts deployed on strict-PQ chains expose only the PQ Permit interface; contracts that need both expose two separate methods and operators disable the classical method on profile activation.

Reference implementation

luxfi/consensus/protocol/auth/permit.go (auth-pq-surface). EVM precompile binding: luxfi/coreth/core/vm/contracts_pq.go. KAT vectors: luxfi/consensus/protocol/auth/testdata/permit_v1.json.

Security considerations

deadline bounds the permit's validity; off-chain leakage past the deadline is harmless. Per-owner nonce prevents replay within validity window. Cross-chain replay prevented by chain_id. Cross-contract replay prevented by verifying_contract. Cross-profile replay prevented by profile_id. ML-DSA-65 signature size (~3309 B) makes the permit unsuitable for tightly gas-constrained chains but well within Lux gas budget; profile activation should be accompanied by gas-schedule update (HIP-0104 ยง"Gas schedule").

References

  • EIP-2612 โ€” secp256k1 baseline (superseded under strict-PQ).
  • HIP-0085, HIP-0086 โ€” AccountID and TxAuthEnvelope.
  • HIP-0104 โ€” Z-Chain auth precompile.
  • NIST FIPS 204, FIPS 202, SP 800-185, SP 800-57.
  • luxfi/consensus/protocol/auth/permit.go.

CC0.