Skip to content
Minerva. Post-quantum, proof of work.

Documentation · Protocol

PQ-Native Transaction Layer

network/docs/architecture/pq-native-transaction-layer.md · commit e561109 · 2026-10-23

Non-Negotiable Outcome

Minerva-native means No EOA anywhere.

Every externally visible account used by the wallet, miner reward recipient, faucet treasury, relayer/submitter, deployer, protocol/admin control, and public launch material must be a Minerva wallet address backed by a Minerva Account or a stricter PQ policy. ECDSA/secp256k1 addresses and private keys are not part of the Minerva-native launch path.

A Minerva-native testnet or mainnet must not require:

  • MINERVA_DEPLOYER_PRIVATE_KEY
  • MINERVA_FAUCET_PRIVATE_KEY
  • MINERVA_PQ_RELAYER_PRIVATE_KEY
  • MINERVA_MINER_PRIVATE_KEY
  • legacy Ethereum transaction types 0x00, 0x01, or 0x02

Those names remain documented only so existing scaffold code cannot be mistaken for the final architecture.

Required Protocol Change

Smart accounts alone are not enough. If the chain accepts only Ethereum raw transactions, some EOA still has to sign deployment, gas payment, relaying, faucet, or bootstrap transactions. Removing EOAs requires a native transaction path in the node.

Minerva's PQ-native transaction type, MinervaPQTxV1 (called MinervaPQTxV1 in older material), is accepted through eth_sendRawTransaction as a custom typed transaction or through minerva_sendRawPQTransaction (minerva_sendRawPQTransaction remains as a deprecated alias).

Implementation status:

  • CoreGeth reserves typed transaction 0x4D as MinervaPQTxType (MinervaPQTxType is a source-compatible alias). 0x04 is EIP-7702 on Ethereum and is never accepted.
  • MinervaPQTxV1 carries a Minerva wallet address in Account and ML-DSA-65 authorization fields.
  • CoreGeth sender derivation verifies the ML-DSA signature and returns the Minerva wallet address, not an EOA.
  • CoreGeth binds the Minerva wallet address to the canonical MinervaAccountFactory CREATE2 address for (pqPublicKey, factorySalt), so the native transaction sender and deployed smart-account address are the same 0x account.
  • The legacy txpool accepts the typed PQ transaction for devnet testing.
  • State precheck can allow a contract-backed Minerva Account sender only for PQ-native messages.
  • The wallet now produces raw MinervaPQTxV1 bytes with the same signing hash and typed transaction encoding that CoreGeth validates.
  • A cross-repo fixture test checks the wallet signing hash and raw transaction hash against CoreGeth decoding.
  • CoreGeth exposes minerva_sendRawPQTransaction for PQ-only raw transaction submission and keeps eth_sendRawTransaction for standard typed transaction compatibility. minerva_getAccountControl returns the control record the node enforces.
  • Devnet genesis prefunds a deterministic Minerva wallet address and installs the canonical account factory/registries at system addresses, and pnpm devnet:pq-native-raw-smoke submits a live raw MinervaPQTxV1 without a relayer or EOA sender.
  • The native-only rule is a chain-config fork (minervaNativeOnlyFBlock) enforced in block validation, state processing, and ApplyTransaction: a block containing any non-Minerva transaction type is invalid on every node, whatever the miner's local policy. MINERVA_EOA_TXS=0 remains only as a deprecated local txpool/RPC policy for networks that have not activated the fork.
  • The faucet now signs bounded devnet grants as native MinervaPQTxV1 transactions from the genesis-funded ML-DSA account.
  • The PQ relayer service is a raw transaction gateway; it submits wallet-signed 0x4D bytes and no longer owns an EOA gas-payer key.
  • pnpm devnet:soak repeatedly submits native PQ transactions and pnpm devnet:multinode-smoke verifies two local CoreGeth nodes peer, sync, and mine a PQ transaction submitted through the non-mining peer.
  • pnpm devnet:pq-smoke funds a counterfactual Minerva Account, deploys it through the canonical factory using PQ-native gas, and executes executePQ from the deployed account without an EOA.
  • Remaining implementation slice: production PQ vault/policy integration for public testnet/mainnet operations.

The transaction must carry enough data for CoreGeth to validate account control before execution:

  • chainId
  • nonce
  • maxFeePerGas
  • maxPriorityFeePerGas
  • gasLimit
  • accountAddress
  • factorySalt
  • pqPublicKey
  • target
  • value
  • data
  • context
  • signature

The signature domain must bind the Minerva network, transaction version, chain ID, account address, nonce, gas fields, target, value, calldata hash, and context. Breaking ECDSA/secp256k1 must not help an attacker create or submit a valid Minerva-native transaction.

Sender And Address Rule

The sender is the Minerva wallet address, not an EOA.

For v1, the canonical sender is the deterministic MinervaAccount address derived from:

  • the canonical account factory address
  • the wallet's ML-DSA-65 public key commitment
  • the wallet salt
  • the account bytecode hash

If the account is not deployed yet, the node may allow first-use deployment through the canonical factory path, but the sender remains the counterfactual Minerva Account address. Gas is charged to the Minerva Account balance.

Node Responsibilities

CoreGeth must be changed so Minerva-native networks can:

  • decode MinervaPQTxV1
  • reject malformed PQ transactions in the transaction pool
  • verify ML-DSA-65 signatures before state transition
  • derive the sender as the Minerva Account address
  • charge gas to the Minerva Account balance
  • execute the account call path without an EOA gas payer
  • reject replay by enforcing the account nonce
  • expose mining status, receipts, logs, and balances through standard Ethereum read RPC
  • reject legacy Ethereum transaction types once minervaNativeOnlyFBlock is active (a consensus rule, not a local policy)

The ML-DSA verifier precompile at 0x0000000000000000000000000000000000004D00 (activated by minervaMLDSA65PrecompileFBlock; 0x...0100 is left to RIP-7212 / EIP-7951) remains the shared verification primitive. The transaction layer calls the same Go verifier directly during transaction validation.

Genesis And Deployment

Minerva-native launch material must not deploy contracts with an EOA.

The devnet genesis file installs:

  • ML-DSA-65 precompile activation
  • canonical MinervaAccountFactory at 0x0000000000000000000000000000000000000203
  • SecurityModeRegistry at 0x0000000000000000000000000000000000000201
  • AccountReadinessRegistry at 0x0000000000000000000000000000000000000202
  • initial PQ treasury wallet address
  • initial faucet policy account, if used
  • miner reward recipient as a Minerva wallet address

The miner etherbase is only a reward recipient. It must be a Minerva wallet address; it does not need an EOA private key because consensus credits block rewards directly to the configured coinbase address.

Service Model

The faucet and relayer become PQ submitters, not EOA signers.

  • The wallet signs a MinervaPQTxV1 with ML-DSA.
  • The gateway or submitter forwards the raw PQ transaction.
  • A faucet policy can authorize bounded MRV grants from a Minerva Account.
  • No service owns a gas-payer EOA.
  • No service can move funds by producing an ECDSA signature.

Service env should eventually point to Minerva wallet vaults, policy files, and public endpoints, not Ethereum private keys.

Network Policy

Minerva devnet/testnet/mainnet genesis files activate minervaNativeOnlyFBlock, minervaMLDSA65PrecompileFBlock, minervaAccountControlFBlock, and minervaEmissionFBlock at block 0 and install system contracts at genesis instead of EOA deployment. MINERVA_EOA_TXS=0 is no longer required.

Minerva-native testnet and mainnet policy is:

  • No EOA anywhere.
  • Legacy Ethereum transaction types disabled.
  • All launch addresses are Minerva wallet addresses.
  • Protocol/admin accounts are Minerva Accounts or stricter PQ policies.
  • Faucet and submitter flows use ML-DSA authorization.
  • Public docs and explorer pages must not describe EOA paths as Minerva-native.

Minerva Account Control

Sender derivation alone binds a native transaction to the account's initial key through the CREATE2 address. That is correct before deployment and wrong after a key rotation, so Minerva adds a consensus check for deployed accounts:

  • MinervaPQTxV1 carries pqAlgorithm and policyVersion, both covered by the signing hash, and the ML-DSA context is the constant MINERVA_PQ_TX_V1.
  • AccountControlRegistry at 0x0000000000000000000000000000000000000204 holds (commitment, algorithm, policyVersion) per account. Only the account writes its own record; the version can only increase. The account writes it at construction (version 0) and on every rotatePQKey (version + 1).
  • Before charging gas (and at txpool admission) the node reads the record: a counterfactual account must use policy version 0 and the CREATE2 binding; a deployed account must carry the current commitment, algorithm, and policy version. A rotated-out key is rejected with ErrMinervaStaleControlKey.
  • Gated by minervaAccountControlFBlock. The storage layout is pinned by a Foundry test and a Go round-trip test because the node reads the slots directly.

Emission on Minerva networks is the genesis blockReward schedule (1 MRV, halving every 10,500,000 blocks, zero from halving 60) paid to the block winner only; uncle blocks earn nothing, so issuance equals the schedule exactly. The difficulty bomb is disposed at genesis.

Device Keys (Minerva)

An account can enrol additional ML-DSA-65 keys ("device keys") with a scope. The split of responsibilities is deliberate:

  • Registry (AccountControlRegistry, slot 1): deviceKeys[account][commitment] packed as algorithm | enrolledVersion | active | exists, written only by the account on enrollDeviceKey / revokeDeviceKey, both of which bump policyVersion.
  • Node (core.ValidateMinervaAccountControl): a native transaction whose key is not the control key must be an active device key, carry the account's current policyVersion, and be a zero-value call to the account itself. Everything else is rejected at txpool admission and in block validation (ErrMinervaDeviceKeyScope, ErrMinervaDeviceKeyRevoked).
  • Precompile MINERVA_TX_CONTEXT (0x...4D01, fixed 100 gas, active with the account-control rule): returns abi.encode(account, keyCommitment, algorithm, policyVersion, factorySalt) of the native transaction being executed, zeros for any other transaction.
  • Account (MinervaAccount.executeNative): self-call only; reads the signer from the precompile; control key unrestricted; device key bound to allowed targets (or any), a value limit per window (or lifetime), an expiry, and protected targets (the account itself and the registries) that no scope can include. A device key therefore cannot rotate, enrol, revoke or rewrite the registry.
  • RPC: minerva_getDeviceKey(account, commitment[, block]) returns the record plus the account's current policy version. The SDK uses it to fill policyVersion for a device key.

Live acceptance: pnpm devnet:pq-device-key-smoke (enrol, scope hits and misses, revocation refused at consensus).

Acceptance Gate

The transition is not complete until:

pnpm pq-native:acceptance
pnpm coregeth:test
pnpm contracts:test

plus an integration test can start a fresh Minerva-native network, mine blocks, fund a Minerva wallet address through PQ policy, submit a PQ-native transaction without any EOA private key, and confirm the receipt.