aere-docs/DOVADA-PQC-VERIFICABILA-2026-07-20.md
Aere Network dd1410c266 The unpublished line of work joins the sanitized public line
The published line and the local line of this repository had no common
ancestor: the public one carried the hygiene pass (no host names, no internal
paths), the local one carried a month of corrections that never shipped. This
commit ports the local work onto the public line, keeping the public hygiene
wording wherever the two touched the same sentence, and keeping the public
version of AERE-CROSS-CLIENT-DETERMINISM.md entirely.

Carried: LICENSE/LICENSING corrections, VERIFY-POLICY.md,
CITATIONS-UNRESOLVED.md remeasured 2026-08-11, the 'audited' adjective removed
from next to Bouncy Castle, citation paths rewritten to published form, AIP-8,
the QA consolidation report, the second EIP validation pass, fork-height
corrections, the AereSink / threshold-factory correction, the forge test
floor, and the architecture-map updates.
2026-08-15 13:54:42 +03:00

20 KiB

Dovada PQC verificabila. Tested commands and real output

Date: 2026-07-20 Chain: AERE mainnet, chain ID 2800 (0xaf0) Endpoints used: https://rpc.aere.network and https://rpc2.aere.network Head at time of measurement: 10,615,742 rising to 10,617,158 during the run

Every command below was executed against the live public RPC before being written down. Output is pasted verbatim. Where something did not verify, this document says so explicitly.


0. The problem this document fixes

We publish "the post-quantum precompiles activated at block 9,189,161" and invite the reader to check it. A stranger who follows that pointer finds an empty block. The activation is real, the number is correct, but the pointer is useless as evidence, because the activation was a fork configuration change and not a transaction. There is no artifact in that block to look at.

The number stays. The evidence changes.


1. Confirmed: block 9,189,161 is empty, on both endpoints

curl -s -X POST https://rpc.aere.network -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["0x8c3729",false]}'

0x8c3729 is 9,189,161. Measured, both endpoints, identical:

Block Timestamp Tx count gasUsed Hash
9,189,160 1783820271 0 0x0 0x6ecfa50257f2de5953d22baa27843ce55fd09a3f26adbc060264b97f09ee804a
9,189,161 1783820272 0 0x0 0x3cb61a23dfc7065cce44fb62108a36bb3f4147bb851ddd9bdec374eba4a337cf
9,189,162 1783820272 0 0x0 0x999acabe0c2add28977ab78ccf2f8f16b245a2e110d5934ddedabe14d11a0aa4

rpc.aere.network and rpc2.aere.network returned byte-identical hashes for all three blocks.

The finding is confirmed. Block 9,189,161 contains zero transactions. Pointing a reader at explorer.aere.network/block/9189161 as proof of the activation hands a critic a working counterexample.


2. What survives as evidence. Four candidates, all tested

2.1 eth_config. SOLID, and the single best artifact

This was not used anywhere in our public copy. It is the strongest and simplest proof, because the live node states the activation time and the active precompile set in one call, at latest, with no historical state involved.

curl -s -X POST https://rpc.aere.network -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_config","params":[]}'

Real output, abbreviated to the relevant fields, identical on both endpoints:

{ "result": { "current": {
    "activationTime": 1783820272,
    "chainId": "0xaf0",
    "forkId": "0xce69e400",
    "precompiles": {
      "AereFalcon512":   "0x0000000000000000000000000000000000000ae1",
      "AereFalcon1024":  "0x0000000000000000000000000000000000000ae2",
      "AereMLDSA44":     "0x0000000000000000000000000000000000000ae3",
      "AereSLHDSA128s":  "0x0000000000000000000000000000000000000ae4",
      "AereSHAKE256":    "0x0000000000000000000000000000000000000ae5",
      "P256VERIFY":      "0x0000000000000000000000000000000000000100",
      "ECREC": "0x...01", "SHA256": "0x...02", "RIPEMD160": "0x...03", "ID": "0x...04",
      "MODEXP": "0x...05", "BN254_ADD": "0x...06", "BN254_MUL": "0x...07",
      "BN254_PAIRING": "0x...08", "BLAKE2F": "0x...09", "KZG_POINT_EVALUATION": "0x...0a",
      "BLS12_G1ADD": "0x...0b", "BLS12_G1MSM": "0x...0c", "BLS12_G2ADD": "0x...0d",
      "BLS12_G2MSM": "0x...0e", "BLS12_PAIRING_CHECK": "0x...0f",
      "BLS12_MAP_FP_TO_G1": "0x...10", "BLS12_MAP_FP2_TO_G2": "0x...11"
    },
    "systemContracts": {
      "BEACON_ROOTS_ADDRESS":   "0x000f3df6d732807ef1319fb7b8bb8522d0beac02",
      "HISTORY_STORAGE_ADDRESS":"0x0000f90827f1c53a10cb7a02335b175320002935"
    }
}, "next": null, "last": null } }

Two things this proves at once:

  1. activationTime is 1783820272, which is exactly the timestamp of block 9,189,161 in section 1.
  2. The active precompile set contains exactly five Aere entries, 0x0AE1 through 0x0AE5. 0x0AE6 and 0x0AE7 are not in the list. The live node itself confirms they are not on mainnet.

2.2 First block at or after activationTime. SOLID

The link from the timestamp to the block number is a binary search over header timestamps. Headers are full history, so this works at any depth and needs no state.

# 23 eth_getBlockByNumber calls, binary search for the first block with timestamp >= 1783820272

Real output:

binary search for first block with timestamp >= 1783820272
  result block   : 9189161   (23 rpc calls)
  ts(block)      : 1783820272
  ts(block-1)    : 1783820271
  matches claim 9189161: True

This is what makes the published number defensible. 9,189,161 is not an assertion taken from a config file that the reader must trust. It is the block the reader derives themselves from activationTime, which the node publishes. The block is empty, and that is expected and fine, because its significance is its timestamp, not its contents.

2.3 Attestation receipt at block 9,200,532. SOLID

Receipts and logs are full history and are unaffected by the 512-block state window.

curl -s -X POST https://rpc.aere.network -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["0xcd1350372f0a61e26e8a3228da599be9211839f378eef0ea49f2025a20920660"],"id":1}'

Measured:

Field Value
Status 0x1 (success)
Block 9,200,532
Block hash 0x719402887c204b4e6674a34911259ead10986efa744b550b209ea571d986a88a
To 0x465d9e3b476bf98aa1393079e240db5d2a9bea6a (AerePQCAttestation)
Gas used 1,386,367
Logs 1, topic0 0x8cf3c7a52148b21f2af90768d73b55c8115c55af53d5d36f5c14b39108789648

Why a successful receipt is proof. AerePQCAttestation.attest() reverts unless the precompile returns a 32-byte word ending in 0x01. A staticcall to an address with no precompile succeeds with empty return data, which fails the ret.length >= 32 check, which reverts the transaction. A recorded status 0x1 therefore cannot happen on a chain where the precompile is absent.

Corroboration, measured at latest: the contract runtime bytecode is 4,402 bytes and contains references to 0x0AE1, 0x0AE2, 0x0AE3 and 0x0AE4.

2.4 Live gas differential at latest. SOLID, and the strongest live proof

Full method and results in section 3.

2.5 What did NOT work, stated explicitly

  • eth_call to 0x0AE1 at block 9,189,161 returns -32603 Internal error. Historical state is pruned. Do not put this in any instruction.
  • eth_getCode / eth_getBalance / eth_getStorageAt at that height return null. Same reason.
  • The return-value test ("live returns a 32-byte word, absent returns 0x") is not sound and must not be published as the liveness proof. See section 3.1.

3. The gas differential, done correctly

3.1 Why the previous attempt recorded a bad proof

A previous run concluded 0x0AE6 and 0x0AE7 were "not live" because they "returned empty 0x". That reasoning is invalid. A live precompile that rejects malformed input can also return empty, and a codeless address returns empty while reporting success, so the two cases are indistinguishable from the return value alone.

Measured demonstration:

0x0AE1 (LIVE, garbage input) -> 0x0000...0000   (32-byte zero word)
0x0AE6 (ABSENT)              -> 0x
0xdead (codeless control)    -> 0x

In this particular instance 0x0AE1 happens to return a zero word rather than empty, so the test appears to work. That is incidental to how this one precompile handles malformed input. It is not a general discriminator, and the conclusion must not rest on it. Gas is the sound discriminator, because a codeless address consumes zero execution gas and a live precompile cannot.

3.2 The method

Deploy a probe via eth_call state override. The probe reads GAS, performs a CALL to the target, reads GAS again, and returns the difference. Two corrections matter and were both applied:

  1. Pre-expand memory before the first GAS reading, with MSTORE(0xA000, 0). Without this, the CALL's memory expansion charge (about 7,040 gas) lands inside the measurement and varies with input length, which swamps the signal.
  2. Pre-warm the target address with a throwaway CALL before the first GAS reading. Without this, EIP-2929 charges 2,600 for a cold address and 100 for a warm one. Standard precompiles are pre-warmed and an arbitrary control address is not, which produces a false negative delta.

The measured value is then target_cost - control_cost, which is pure execution gas.

Probe bytecode, for target T (20 bytes, no 0x):

0x366000600037 6000 61a000 52 6000600060006000600073<T>612710f150
  5a 612000 618000 36 6000 6000 73<T> 6305f5e100 f1 50 5a 90 03 600052 60206000f3

Copy-pasteable form, Falcon-512 at 0x0AE1:

curl -s -X POST https://rpc.aere.network -H 'content-type: application/json' -d '{
 "jsonrpc":"2.0","id":1,"method":"eth_call","params":[
  {"to":"0x000000000000000000000000000000000000b0b0",
   "data":"0x3333333333333333333333333333333333333333333333333333333333333333",
   "gas":"0x1c9c380"},
  "latest",
  {"0x000000000000000000000000000000000000b0b0":{"code":"0x366000600037600061a0005260006000600060006000730000000000000000000000000000000000000ae1612710f1505a6120006180003660006000730000000000000000000000000000000000000ae16305f5e100f1505a900360005260206000f3"}}]}'

Swap the two occurrences of 0000000000000000000000000000000000000ae1 for any other address to measure that address. Use 000000000000000000000000000000000000dead as the codeless control.

3.3 Calibration. Run this FIRST, before trusting any number

The IDENTITY precompile at 0x04 costs exactly 15 + 3*ceil(len/32). If the probe does not reproduce that formula, the probe is wrong and every other number from it is worthless.

Real output:

CALIBRATION: IDENTITY 0x04, expected = 15 + 3*ceil(len/32)
len      raw(0x04)  raw(ctrl)  measured   expected
32       142        124        18         18         MATCH
320      169        124        45         45         MATCH
1024     235        124        111        111        MATCH
4096     523        124        399        399        MATCH

calibration PASSED

Second calibration on SHA256 at 0x02, which costs 60 + 12*ceil(len/32):

   len=32    measured=72       expected=72
   len=320   measured=180      expected=180

Both calibrations are exact at every length tested. The probe is trustworthy.

3.4 Results, measured at block 10,615,742 at latest

Input 0x33 repeated, at three lengths, on rpc.aere.network:

Precompile len=32 len=1024 len=2048 Verdict
0x0AE1 Falcon-512 40,000 40,000 40,000 LIVE
0x0AE2 Falcon-1024 75,000 75,000 75,000 LIVE
0x0AE3 ML-DSA-44 55,000 55,000 55,000 LIVE
0x0AE4 SLH-DSA-128s 350,000 350,000 350,000 LIVE
0x0AE5 SHAKE256 24,636 25,008 25,392 LIVE (length dependent)
0x0AE6 ML-KEM-768 0 0 0 ABSENT, identical to codeless control
0x0AE7 Falcon HashToPoint 0 0 0 ABSENT, identical to codeless control

Independently reproduced on rpc2.aere.network, identical values: 40,000 / 75,000 / 55,000 / 350,000 / 24,636 / 0 / 0.

3.5 Cross-check against the node source. Independent corroboration

The measured constants match the gas schedule in aere-node/patches/0001-aere-pqc-precompiles-mainnet.patch:

line 279:  private static final long GAS = 40_000L;   // Falcon-512   0x0AE1
line 211:  private static final long GAS = 75_000L;   // Falcon-1024  0x0AE2
line 352:  private static final long GAS = 55_000L;   // ML-DSA-44    0x0AE3
line 562:  private static final long GAS = 350_000L;  // SLH-DSA-128s 0x0AE4
line 460:  static final int MAX_OUTPUT  = 1 << 16;    // SHAKE256     0x0AE5
line 462:  private static final int BASE_GAS = 60;
line 463:  private static final int GAS_PER_WORD = 12;

SHAKE256 is BASE_GAS + GAS_PER_WORD * (ceil(dataLen/32) + ceil(outLen/32)). The 0x33-filled input above encodes a huge output length, which the contract caps at MAX_OUTPUT = 65,536 = 2,048 words, giving 60 + 12*2048 = 24,636, exactly the measured value.

Verified with well-formed inputs, outLen as a 32-byte big-endian prefix:

  outLen=32    dataLen=32    measured=84     expected=84     MATCH
  outLen=32    dataLen=1024  measured=456    expected=456    MATCH
  outLen=64    dataLen=0     measured=84     expected=84     MATCH
  outLen=256   dataLen=256   measured=252    expected=252    MATCH

On-chain measured gas equals the published source constants. This is the corroboration that makes the live proof self-contained: a stranger measures the gas, reads the source, and the two agree.

3.6 Correction to the previously recorded numbers

Prior record: control 23,897; 0x0AE1 62,853; 0x0AE2 97,992; 0x0AE3 77,913; 0x0AE4 376,144; 0x0AE5 47,055; 0x0AE6 and 0x0AE7 both 23,897.

Those absolutes were whole-call totals, including the 21,000 intrinsic transaction cost, calldata cost and probe overhead. They are not precompile execution costs. A separate review recorded a control of 61,825, different again, for the same reason. Subtracting each run's own control gets close to the true values but not exactly, because the overhead does not cancel cleanly.

Corrected: the execution costs are 40,000 / 75,000 / 55,000 / 350,000 and 60 + 12*words for SHAKE256. These are round numbers because they are literal constants in the client, and they now match the source line for line.

Confirmed unchanged: the conclusion that 0x0AE6 and 0x0AE7 are absent on mainnet. They measure exactly the codeless control in both the old run and this one, and eth_config independently omits them from the precompile list. Two independent methods agree.


4. Why this document does not reconstruct block hashes

A proposed replacement wording instructed the reader to re-encode extraData with the seals list emptied and the round set to zero, and to recover each committed seal by ECDSA. As written it would fail at block 1, and it is not needed for the PQC claim. Measured header field sets:

Block Optional header fields present
1 baseFeePerGas, withdrawalsRoot (2 fields)
9,189,161 baseFeePerGas, withdrawalsRoot, blobGasUsed, excessBlobGas, parentBeaconBlockRoot, requestsHash (6 fields)
latest same 6 fields

extraData is also 238 bytes at blocks 1 and 9,189,161 but 525 bytes at latest, because the validator set grew and the seal list with it. Any instruction that hardcodes one field set or one extraData layout breaks on the other era.

Header reconstruction is a real capability and it does work, at 2 fields for pre-Pectra blocks and 6 for post-Pectra blocks. It is simply the wrong tool for proving precompile activation, and it adds a large failure surface to an instruction that does not need it. It is out of scope here and should be documented separately, with the field count stated per era and tested at both eras.


5. The corrected instruction, for publication

Verify the post-quantum precompiles yourself

No wallet, no gas, no account. Two commands.

1. Ask the network what is active.

curl -s -X POST https://rpc.aere.network -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_config","params":[]}'

The response lists activationTime: 1783820272 and the five Aere precompiles at 0x0AE1 through 0x0AE5. Block 9,189,161 is the first block whose timestamp is at or after that activation time, which you can confirm by binary search over eth_getBlockByNumber timestamps. That block contains no transactions, because the activation was a fork configuration change and not a transaction. Its significance is its timestamp, not its contents. Repeat against https://rpc2.aere.network for an independent second endpoint.

2. Prove they are executing right now, by measuring gas.

A live precompile consumes gas. An address with nothing at it consumes none. Return values do not settle this, because an empty address returns empty data and reports success. Gas does.

The command in section 3.2 deploys a throwaway measuring probe via eth_call state override and returns the gas consumed by one call to the target. Calibrate it first against the IDENTITY precompile at 0x04, whose cost is fixed by the EVM specification at 15 + 3*ceil(len/32). For a 32-byte input it must read exactly 18 more than the codeless control. Then measure:

Address Measured gas above control Meaning
0x04 IDENTITY 18 calibration, matches the EVM spec
0x0AE1 Falcon-512 40,000 live
0x0AE2 Falcon-1024 75,000 live
0x0AE3 ML-DSA-44 55,000 live
0x0AE4 SLH-DSA-128s 350,000 live
0x0AE5 SHAKE256 60 + 12 per word live
0x0AE6, 0x0AE7 0 not on mainnet, testnet only

Those constants are in the client source, so your measurement and our published code can be compared directly.

Optional, to check the past. Historical account state is pruned after 512 blocks, so a historical eth_call will not work. Receipts are kept in full. Receipt 0xcd1350372f0a61e26e8a3228da599be9211839f378eef0ea49f2025a20920660 is a successful post-quantum attestation at block 9,200,532, status 0x1, 1,386,367 gas. That contract reverts unless the precompile returns a valid result, so a successful receipt could not exist on a chain without the precompile.

Scope, stated plainly. Post-quantum signature verification is live on mainnet at the execution layer, and any contract can require it. AERE consensus remains classical secp256k1 ECDSA under QBFT and is not post-quantum. Hybrid post-quantum consensus exists only on an isolated testnet and is audit-gated. 0x0AE6 and 0x0AE7 are testnet only.


6. Provable and not provable

Provable today, by a stranger, measured above:

  • Five NIST post-quantum precompiles execute on mainnet right now, at 0x0AE1 to 0x0AE5, with gas costs matching published source constants.
  • The fork activation time is 1783820272 and block 9,189,161 is the first block at or after it.
  • Post-quantum signature verification recorded successfully on-chain at block 9,200,532.
  • 0x0AE6 and 0x0AE7 are not active on mainnet, by two independent methods.
  • Both public endpoints agree on every value in this document.

Not provable, and must never be claimed:

  • Consensus is not post-quantum. It is classical secp256k1 ECDSA under Hyperledger Besu QBFT.
  • The activation height cannot be proven from block contents, only from the activation timestamp plus header timestamps. The block is empty and always will be.
  • Historical account state before the 512-block window cannot be queried. eth_getBalance returns null and eth_getTransactionCount returns a false 0x0 rather than erroring.

Not verified in this pass, stated so it is not mistaken for verified:

  • I did not read the live QBFT transitions configuration on the validators. activationTime came from the eth_config RPC response, not from a node config file.
  • I did not re-verify the NIST KAT vector replay on quantum.html. A prior review recorded 27/27 passing; I did not independently rerun it.
  • I did not verify the sub-second transition block number. That is a separate open finding.

7. Infrastructure safety

No transaction was sent, no contract deployed, no node touched, no configuration changed. All calls were read-only JSON-RPC (eth_blockNumber, eth_chainId, eth_getBlockByNumber, eth_getTransactionReceipt, eth_getCode, eth_call, eth_config). The eth_call state overrides are simulation-only and write nothing.

RPC health measured after all activity:

rpc.aere.network  attempt 1: 381 ms   {"result":"0xa1fd42"}
rpc.aere.network  attempt 2: 371 ms   {"result":"0xa1fd43"}
rpc.aere.network  attempt 3: 437 ms   {"result":"0xa1fd44"}
rpc2.aere.network attempt 1: 459 ms   {"result":"0xa1fd45"}
rpc2.aere.network attempt 2: 444 ms   {"result":"0xa1fd46"}

All responses well under one second, block height advancing normally.