Files
hips/HIPs/hip-0086-tx-auth-envelope.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
0086 TxAuthEnvelope (typed PQ transaction signing) Standards Track Cryptography Final shipped Hanzo AI 2026-05-11 HIP-0005, HIP-0077, HIP-0078, HIP-0079, HIP-0084, HIP-0085

HIP-0086: TxAuthEnvelope (typed PQ transaction signing)

Abstract

HIP-0086 specifies TxAuthEnvelope, the canonical transaction signing envelope under the strict-PQ profile. Every user-originated transaction commits to (chain_id, account_id, nonce, payload_hash, profile_id, identity_scheme_id, hash_suite_id) via a TupleHash256 transcript (SP 800-185) bound by the cust string TX-AUTH-V1, and is authenticated by an ML-DSA-65 (FIPS 204) signature over the transcript. The verifier is the unmodified FIPS 204 ML-DSA.Verify routine; the envelope is the only thing a strict-PQ chain accepts at the transaction boundary.

Specification

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

TxAuthEnvelope {
    version            uint8       = 0x01
    profile_id         uint8       // 0x01 Lux | 0x04 Zoo | 0x05 Hanzo
    identity_scheme_id uint8       = 0x42  // ML_DSA_65
    hash_suite_id      uint8       = 0x01  // SHA3_NIST
    chain_id           uint64
    account_id         [48]byte    // HIP-0085 AccountID
    nonce              uint64
    payload_hash       [48]byte    // SHA3-384 of canonical payload
    expiration         uint64      // unix seconds; 0 = none
    mldsa_pubkey       []byte      // ~1952 B FIPS 204 pubkey
    mldsa_signature    []byte      // ~3309 B FIPS 204 signature
}

transcript = TupleHash256(
    "TX-AUTH-V1",                  // cust string per SP 800-185
    [ version, profile_id, identity_scheme_id, hash_suite_id,
      chain_id_be8, account_id, nonce_be8, payload_hash,
      expiration_be8, mldsa_pubkey ],
    384                            // output bits = MinHashOutputBits
)

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

Acceptance rule:

  1. profile_id MUST equal the chain's pinned ProfileID; mismatch = reject (ErrProfileMismatch).
  2. identity_scheme_id MUST equal 0x42; any other value rejected.
  3. hash_suite_id MUST equal 0x01.
  4. AccountID == cSHAKE256(profile_be4 || chain_be4 || u8(scheme) || pubkey, 48, "", "LUX_ACCOUNT_ID_V1"), per HIP-0085.
  5. ML-DSA.Verify(mldsa_pubkey, transcript, mldsa_signature) MUST return true under unmodified FIPS 204.
  6. nonce MUST equal the account's next-expected nonce.
  7. If expiration != 0, now < expiration.

Failure of any check is a hard reject; no fallback path.

Backwards compatibility

None. Strict-PQ chains reject classical secp256k1 RLP transactions at the consensus boundary. Permissive profiles (0x02) may accept both during operator-controlled transition windows.

Reference implementation

luxfi/consensus/protocol/auth/tx_envelope.go (auth-pq-surface). Encoders / decoders: luxfi/wallet/pq/tx.go. KAT vectors: luxfi/consensus/protocol/auth/testdata/tx_envelope_v1.json.

Security considerations

The transcript binds profile_id and chain_id; a signature valid on Lux mainnet is not valid on Zoo mainnet nor on a permissive sibling. Replay across nonces is prevented by the account-scoped nonce check. Replay across chains is prevented by chain_id. Replay across profiles is prevented by the profile_id binding. ML-DSA-65 signatures are ~3309 B; an envelope at typical payload sizes is ~5.5 KB on the wire — larger than secp256k1 but well within consensus budget.

References

  • HIP-0085 — AccountID derivation.
  • HIP-0079 — sibling transcript pattern (Q-Block).
  • NIST FIPS 204 — verifier target.
  • NIST SP 800-185 — TupleHash256.
  • NIST SP 800-57 — key management.
  • luxfi/consensus/config/profiles.go — profile pin.
  • luxfi/consensus/protocol/auth/ — canonical implementation.

CC0.