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.
166 lines
7.2 KiB
Python
166 lines
7.2 KiB
Python
#!/usr/bin/env python3
|
|
# Falcon-512 verify gas benchmark: WITH vs WITHOUT the native HashToPoint precompile.
|
|
# Deploys the stock in-EVM verifier (V0) and the precompile-backed variant (V1) on
|
|
# the isolated fork node, runs identical real Falcon-512 KAT vectors through both,
|
|
# and reports receipt gasUsed. Also confirms genuine sigs accept / tampered reject
|
|
# on BOTH (integration KAT for the precompile).
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
# Repository root, resolved from this file's location, so the script runs as-is in
|
|
# a clean checkout. Override with AERE_STAGING. These paths were previously
|
|
# hardcoded to a build operator's home directory, which disclosed an internal
|
|
# layout and made the benchmark unrunnable for anyone else without editing it.
|
|
STAGING = os.environ.get(
|
|
"AERE_STAGING", os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
)
|
|
|
|
from web3 import Web3
|
|
from eth_account import Account
|
|
|
|
RPC = "http://127.0.0.1:8545"
|
|
KEY = "0x0000000000000000000000000000000000000000000000000000000000000001"
|
|
acct = Account.from_key(KEY)
|
|
|
|
w3 = Web3(Web3.HTTPProvider(RPC))
|
|
# QBFT is proof-of-authority: extraData > 32 bytes, needs the POA middleware.
|
|
try:
|
|
from web3.middleware import ExtraDataToPOAMiddleware
|
|
w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
|
|
except Exception:
|
|
from web3.middleware import geth_poa_middleware # older web3
|
|
w3.middleware_onion.inject(geth_poa_middleware, layer=0)
|
|
assert w3.is_connected(), "no RPC"
|
|
CHAIN = w3.eth.chain_id
|
|
|
|
|
|
def compile_all():
|
|
out = subprocess.check_output([
|
|
"solc", "--combined-json", "abi,bin", "--optimize", "--optimize-runs", "200",
|
|
os.path.join(STAGING, "bench", "AereFalcon512Verifier.sol"),
|
|
os.path.join(STAGING, "bench", "AereFalcon512VerifierHTP.sol"),
|
|
])
|
|
j = json.loads(out)
|
|
res = {}
|
|
for name, c in j["contracts"].items():
|
|
short = name.split(":")[-1]
|
|
res[short] = {"abi": c["abi"] if isinstance(c["abi"], list) else json.loads(c["abi"]), "bin": c["bin"]}
|
|
return res
|
|
|
|
|
|
def gas_price():
|
|
blk = w3.eth.get_block("latest")
|
|
base = blk.get("baseFeePerGas", 0) or 0
|
|
return int(base) * 2 + 10 ** 9
|
|
|
|
|
|
def send(tx):
|
|
tx.setdefault("chainId", CHAIN)
|
|
tx.setdefault("nonce", w3.eth.get_transaction_count(acct.address))
|
|
tx.setdefault("gas", 40_000_000)
|
|
tx.setdefault("gasPrice", gas_price())
|
|
signed = acct.sign_transaction(tx)
|
|
raw = getattr(signed, "raw_transaction", None) or signed.rawTransaction
|
|
h = w3.eth.send_raw_transaction(raw)
|
|
return w3.eth.wait_for_transaction_receipt(h, timeout=120)
|
|
|
|
|
|
def deploy(art):
|
|
c = w3.eth.contract(abi=art["abi"], bytecode=art["bin"])
|
|
tx = c.constructor().build_transaction({"from": acct.address, "gas": 12_000_000,
|
|
"gasPrice": gas_price(), "nonce": w3.eth.get_transaction_count(acct.address),
|
|
"chainId": CHAIN})
|
|
r = send(tx)
|
|
assert r.status == 1, "deploy failed"
|
|
return w3.eth.contract(address=r.contractAddress, abi=art["abi"]), r.gasUsed
|
|
|
|
|
|
def parse_sm(sm: bytes):
|
|
siglen = (sm[0] << 8) | sm[1]
|
|
nonce = sm[2:42]
|
|
msglen = len(sm) - 2 - 40 - siglen
|
|
message = sm[42:42 + msglen]
|
|
return nonce, message
|
|
|
|
|
|
def main():
|
|
vec_path = sys.argv[1] if len(sys.argv) > 1 else os.path.join(STAGING, "kat", "falcon512_bench_vectors.txt")
|
|
out_path = sys.argv[2] if len(sys.argv) > 2 else os.path.join(STAGING, "bench", "bench-results.json")
|
|
|
|
# --- precompile liveness sanity ---
|
|
sample = (bytes([9]) + b"\x00" * 40 + b"abc")
|
|
htp_out = w3.eth.call({"to": "0x0000000000000000000000000000000000000AE7", "data": "0x" + sample.hex()})
|
|
assert len(htp_out) == 1024, f"0x0AE7 not active (got {len(htp_out)} bytes)"
|
|
print(f"precompile 0x0AE7 live: returned {len(htp_out)} bytes for logn=9")
|
|
|
|
arts = compile_all()
|
|
v0, g0_deploy = deploy(arts["AereFalcon512Verifier"])
|
|
v1, g1_deploy = deploy(arts["AereFalcon512VerifierHTP"])
|
|
print(f"deployed V0(in-EVM)={v0.address} gas={g0_deploy} V1(precompile)={v1.address} gas={g1_deploy}")
|
|
|
|
rows = []
|
|
for line in open(vec_path):
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
tc, pk_hex, sm_hex = line.split("|")
|
|
pk = bytes.fromhex(pk_hex)
|
|
sm = bytes.fromhex(sm_hex)
|
|
nonce, message = parse_sm(sm)
|
|
|
|
# correctness (eth_call) — genuine must accept on both
|
|
ok0 = v0.functions.verifySignedMessage(pk, sm).call()
|
|
ok1 = v1.functions.verifySignedMessage(pk, sm).call()
|
|
# tampered must reject on both
|
|
bad = bytearray(sm); bad[-1] ^= 0x01
|
|
bad0 = v0.functions.verifySignedMessage(pk, bytes(bad)).call()
|
|
bad1 = v1.functions.verifySignedMessage(pk, bytes(bad)).call()
|
|
|
|
# gas via state-changing verifyAndRecord (identical calldata both sides)
|
|
r0 = send(v0.functions.verifyAndRecord(pk, sm).build_transaction(
|
|
{"from": acct.address, "gas": 40_000_000, "gasPrice": gas_price(),
|
|
"nonce": w3.eth.get_transaction_count(acct.address), "chainId": CHAIN}))
|
|
r1 = send(v1.functions.verifyAndRecord(pk, sm).build_transaction(
|
|
{"from": acct.address, "gas": 40_000_000, "gasPrice": gas_price(),
|
|
"nonce": w3.eth.get_transaction_count(acct.address), "chainId": CHAIN}))
|
|
|
|
# component gas: standalone hashToPoint estimate on each
|
|
htp0 = v0.functions.hashToPoint(nonce, message).estimate_gas({"from": acct.address})
|
|
htp1 = v1.functions.hashToPoint(nonce, message).estimate_gas({"from": acct.address})
|
|
|
|
row = {"tc": tc, "accept_v0": ok0, "accept_v1": ok1, "reject_tampered_v0": not bad0,
|
|
"reject_tampered_v1": not bad1, "verify_gas_in_evm": r0.gasUsed,
|
|
"verify_gas_precompile": r1.gasUsed, "verify_gas_drop": r0.gasUsed - r1.gasUsed,
|
|
"hashToPoint_gas_in_evm": htp0, "hashToPoint_gas_precompile": htp1}
|
|
rows.append(row)
|
|
print(f"tc{tc} accept v0={ok0} v1={ok1} tamperReject v0={not bad0} v1={not bad1} "
|
|
f"| verify gas {r0.gasUsed} -> {r1.gasUsed} (drop {r0.gasUsed - r1.gasUsed}) "
|
|
f"| HTP {htp0} -> {htp1}")
|
|
|
|
n = len(rows)
|
|
avg = lambda k: sum(r[k] for r in rows) // n
|
|
all_ok = all(r["accept_v0"] and r["accept_v1"] and r["reject_tampered_v0"] and r["reject_tampered_v1"] for r in rows)
|
|
summary = {
|
|
"chainId": CHAIN, "vectors": n, "integration_all_pass": all_ok,
|
|
"avg_verify_gas_in_evm": avg("verify_gas_in_evm"),
|
|
"avg_verify_gas_precompile": avg("verify_gas_precompile"),
|
|
"avg_verify_gas_drop": avg("verify_gas_drop"),
|
|
"avg_verify_pct_drop": round(100 * avg("verify_gas_drop") / avg("verify_gas_in_evm"), 1),
|
|
"avg_hashToPoint_gas_in_evm": avg("hashToPoint_gas_in_evm"),
|
|
"avg_hashToPoint_gas_precompile": avg("hashToPoint_gas_precompile"),
|
|
"deploy_gas_in_evm": g0_deploy, "deploy_gas_precompile": g1_deploy,
|
|
"rows": rows,
|
|
}
|
|
json.dump(summary, open(out_path, "w"), indent=2)
|
|
print("\n=== SUMMARY ===")
|
|
print(json.dumps({k: v for k, v in summary.items() if k != "rows"}, indent=2))
|
|
if not all_ok:
|
|
print("INTEGRATION_FAILED"); sys.exit(3)
|
|
print("BENCH_DONE")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|