aere-research/bench/make-htp-variant.py
Aere Network 4a0b48588c Initial public release
Aere Network public source. Everything here can be checked against the live
chain (chain id 2800, https://rpc.aere.network).

Scope note, stated up front rather than buried: consensus on chain 2800 is
classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at
the signature, precompile, account and transport layers. Nothing here makes the
consensus post-quantum, and no document in it should be read as claiming so.
2026-07-20 01:02:30 +03:00

50 lines
1.9 KiB
Python

#!/usr/bin/env python3
# Derive AereFalcon512VerifierHTP.sol from AereFalcon512Verifier.sol by replacing
# ONLY the in-EVM hashToPoint with a call to the native 0x0AE7 precompile. Every
# other step (SHAKE helpers, decode, ring mul, norm check) is byte-identical, so a
# WITH-vs-WITHOUT gas comparison isolates exactly the HashToPoint cost.
import re
import sys
src_path = sys.argv[1]
out_path = sys.argv[2]
s = open(src_path).read()
# 1. rename the contract
s = s.replace("contract AereFalcon512Verifier {", "contract AereFalcon512VerifierHTP {")
# 2. relax `pure` -> `view` on function declarations (the precompile call is a staticcall = view)
s = re.sub(r"\)(\s*)(public|internal|external|private)(\s+)pure", r")\1\2\3view", s)
# 3. replace the whole hashToPoint function body with a precompile-backed one (brace-matched)
start = s.index("function hashToPoint(")
# walk to the opening brace of the body
brace = s.index("{", start)
depth = 0
i = brace
while i < len(s):
if s[i] == "{":
depth += 1
elif s[i] == "}":
depth -= 1
if depth == 0:
break
i += 1
end = i + 1 # inclusive of closing brace
replacement = (
"function hashToPoint(bytes memory nonce, bytes memory message) public view returns (uint256[512] memory cc) {\n"
" // Native AERE Falcon HashToPoint precompile @ 0x0AE7: logn(1)=9 || nonce(40) || message\n"
" bytes memory input = bytes.concat(bytes1(uint8(9)), nonce, message);\n"
" (bool okp, bytes memory outp) = address(0x0AE7).staticcall(input);\n"
" require(okp && outp.length == 1024, \"htp precompile failed\");\n"
" for (uint256 i = 0; i < 512; i++) {\n"
" cc[i] = (uint256(uint8(outp[2 * i])) << 8) | uint256(uint8(outp[2 * i + 1]));\n"
" }\n"
" }"
)
s = s[:start] + replacement + s[end:]
open(out_path, "w").write(s)
print("wrote", out_path)