The public history carried kat/__pycache__/mlkem768_reference.cpython-314.pyc, a compiled Python artifact embedding the operator's absolute local path. Text secret scanners do not read compiled binaries, which is exactly how it slipped through, and removing it from the tip would have left it reachable through the old root commits. So this repository is republished from a single clean root. This root also carries, from the previously unpublished line of work: - corrected LICENSE year, LICENSING.md, VERIFY-POLICY.md, and CITATIONS-UNRESOLVED.md remeasured 2026-08-11 (101 paths, README aligned) - O-018: run_consensus_verification.py ran 19 of 29 models and reported PASS; it now runs all 29, and computemarket_smt.py gains resolveByTimeout / reclaimUnsettled cases plus a negative control - O-006: the word 'audited' removed from next to Bouncy Castle, twice, after a concurrent edit resurrected it - O-014: prior art named and dated - Algorand's native falcon_verify shipped about ten months before AERE's precompiles; the primacy claim is withdrawn where it was implied - bench/ scripts parametrized so they actually run for an outsider (the earlier textual sanitization left $STAGING unexpanded inside Python strings) - AIP-2/AIP-3 errata with measured figures, spec remeasurements at 2026-08-01, and the spec-zk-stack retractions (owner is an operational key, not the Foundation; 'maximally sound' withdrawn; aggregator V1 deprecated) The redacted bench-host environment files from the sanitized line are kept exactly as published; the unredacted local variants are not carried.
9.4 KiB
AIP-3: Sub-Second Block Period (500 ms QBFT)
Preamble
| Field | Value |
|---|---|
| AIP | 3 |
| Title | Sub-Second Block Period (500 ms QBFT) |
| Author | AERE Foundation |
| Type | Standards Track |
| Category | Core |
| Status | Final |
| Created | 2026-07-11 |
| Requires | None |
| Supersedes | None |
| Superseded-By | None |
| Ratification | Foundation-ratified (pre-decentralization) |
Abstract
This AIP documents the mid-chain transition of AERE's block period from one second to 500 milliseconds, performed as a QBFT configuration transition rather than a chain restart, so that all history, state, and validator keys were preserved. It is a retro-filed record of a change that is already live on chain 2800.
Motivation
AERE targets settlement-grade latency. A one-second block period puts a hard floor of about one second on inclusion latency and worst-case finality. Halving the block period to 500 ms roughly halves both, which materially improves the feel of interactive flows (swaps, payments, wallet confirmations) without any change to the EVM or to application code.
The change had to be done without re-genesising the chain. AERE had already been forced through one full re-genesis (genesis-v2 on 2026-05-07), and losing history again was not acceptable. QBFT supports timed configuration transitions, so the block period could be reduced at a scheduled block with continuity of state and validator identity.
Specification
Mechanism
Hyperledger Besu QBFT reads the initial block period from config.qbft and reads
scheduled overrides from a separate transitions object at the config root.
The transition key is xblockperiodmilliseconds (note: milliseconds, and note the
x prefix, which marks the option experimental in Besu). The correct, and easily
mis-typed, form is:
{
"config": {
"qbft": {
"blockperiodseconds": 1,
"epochlength": 30000,
"requesttimeoutseconds": 4
},
"transitions": {
"qbft": [
{ "block": 2137652, "xblockperiodmilliseconds": 500 }
]
}
}
}
transitions is a sibling of qbft, not a child of it. Besu reads transitions
from the config root (JsonGenesisConfigOptions.java:47) and then the sub key
qbft (TransitionsConfigOptions.getQbftForks()). A transitions object nested
inside config.qbft is never read, parses without any error or warning, and is
silently inert.
Activation
The 500 ms period is in force from block 2,137,652 on chain 2800. Before that block the network produced one-second blocks; from that block onward it produces 500 ms blocks, with the cadence settling into a steady alternating pattern by block 2,137,662. State, account balances, contract code, and the validator set were unchanged across the transition.
Block 2,137,652 is the boundary because it is the first block on chain 2800 whose
timestamp equals its parent's. That is impossible while a one second minimum
period is in force, and it is the reason the block number is not a free choice: a
node configured to transition later than 2,137,652 applies
TimestampMoreRecentThanParent to block 2,137,652
(QbftBlockHeaderValidationRulesetFactory.java:80-83), rejects it, and stops
syncing. Full evidence in aerenew/docs/TRANZITIA-QBFT-SETTLED-2026-07-20.md.
Operational note for fresh nodes
A node synced from genesis against this config applies the transition
automatically. A brand-new isolated chain started from a config like this needs
--sync-min-peers=1 to begin producing, which is an operational detail of
bootstrapping, not part of the consensus rule.
Rationale
A configuration transition was chosen over a re-genesis because it preserves the chain's entire history and, critically, the validator keys and account state. Re-genesis was rejected: it destroys history and forces every integrator to re-point. QBFT's timed transition is purpose-built for exactly this kind of parameter change and avoids a client fork.
500 ms was chosen as a conservative first step below one second. It roughly halves latency while staying comfortably within what a small, low-latency, Foundation-operated validator set can sustain. Going lower (for example 250 ms or 100 ms) is possible in principle but was deliberately not attempted here, because tighter periods increase the rate of missed-proposal rounds and stress peer-to-peer timing, and there is no need to push that limit with the current validator topology.
Backwards Compatibility
None at the application layer. Block time is not part of the EVM; contracts do not
observe it directly. Note the second-order effect: any code that assumed a
one-second block period to convert block counts to wall-clock time (for example a
naive per-block reward constant) is now wrong by 2x. AERE hit exactly this: the
original staking contract computed rewards against a hardcoded blocks-per-year
constant and under-paid once blocks sped up. That was fixed in AereStakingV2
(0x1D95eF6D17aeAB732dF914Ba2d018c270BC155FC) by moving reward accrual to
timestamps, which is block-time-immune. New code MUST use block.timestamp, not
block height, for wall-clock math.
Security Considerations
Reducing the block period narrows the timing margin for each consensus round. With the current seven validators under a single operator this is low-risk because network latency between the nodes is small and predictable, and QBFT finalizes within the round among a small set. The honest caveats:
- Small, single-operator validator set. Sub-second finality here is a property of a seven-node, one-operator topology, not of a large decentralized set. It should not be read as a claim about behavior under a geographically dispersed, independently operated validator set. Reassessing the block period will be part of decentralizing the validator set.
- No consensus-layer change beyond the parameter. This is a timing parameter, not a new consensus algorithm. It does not alter QBFT's fault tolerance assumptions.
Reference Implementation and On-Chain Deployment
This is a chain-configuration change, so there is no contract address. The
authoritative artifacts are the Besu QBFT genesis/config carrying the
xblockperiodmilliseconds: 500 transition at block 2,137,652 (see Erratum 1),
and the chain history itself: block intervals before 2,137,652 are 1000 ms and
after are approximately 500 ms, verifiable via eth_getBlockByNumber timestamp
deltas on https://rpc.aere.network. Chain ID is 2800.
Errata
Erratum 1, 2026-07-20. The Mechanism JSON example was self-contradictory, and the activation block was wrong.
As originally published, the prose in Mechanism correctly described a transitions
block, but the JSON example nested transitions inside qbft, which is a form
Besu never reads. The example was:
{
"_note": "WRONG-FORM, historical record of the original defect. Do not copy.",
"config": {
"qbft": {
"blockperiodseconds": 1,
"transitions": { "qbft": [ { "block": 2138451, "xblockperiodmilliseconds": 500 } ] }
}
}
}
That fence is retained above only as the historical record of the defect. It is marked WRONG-FORM so the regression test skips it. It must not be copied.
Two things were corrected in the body:
- Path.
transitionsmoved from insideconfig.qbftto the config root, as a sibling ofqbft. Settled from the Besu 26.4.0 source (JsonGenesisConfigOptions.java:47,TransitionsConfigOptions.getQbftForks()). - Activation block.
2,138,451corrected to2,137,652. The original figure was not measured. Live block timestamps show the one second cadence ending at block 2,137,651, and block 2,137,652 carries the same timestamp as its parent, which a one second period forbids. The2,138,451figure is roughly 800 blocks too late and would halt a from-genesis sync at 2,137,652.
The key name xblockperiodmilliseconds was correct as originally published and is
unchanged. The 500 ms value is unchanged. Nothing about the deployed network
changed; only this document's description of it was wrong.
Evidence and Besu source citations: aerenew/docs/TRANZITIA-QBFT-SETTLED-2026-07-20.md.
Post-Acceptance Outcome Record
Appended 2026-07-20 under AIP-1 section 5. Nothing above this heading was edited.
Measured block interval: 516.4 ms. Configured target: 500 ms.
The transition worked: history, state and validator keys were preserved, and intervals before block 2,137,652 (see Erratum 1) are 1000 ms while intervals after are approximately 500 ms, as the sections above describe. But the realized mean interval is 516.4 ms (measured), roughly 3.3% above the 500 ms target, not 500 ms exactly.
This is expected behavior rather than a defect: xblockperiodmilliseconds sets a
minimum period, and QBFT adds real proposal, gossip and commit latency on top of
it. A configured target and a measured cadence are different quantities.
The obligation this creates. Aere documents state the target as a configuration value and the interval as a measured value, and never present 500 ms as a measured result. Any derived figure that depends on block cadence, including the EIP-2935 lookback duration quoted in AIP-7 and AIP-18 as "roughly 68 minutes", is computed from the target and is therefore an approximation that runs about 3% optimistic; at the measured 516.4 ms cadence, 8191 blocks is approximately 70.5 minutes.
Copyright
Released to the public domain (CC0). No rights reserved.