aere-contracts/contracts/pqc/mocks/RealFalcon512PrecompileAdapter.sol
Aere Network a13a649b77
Some checks are pending
contracts-ci / Install (lockfile) → compile → full test suite (push) Waiting to run
contracts-ci / PQC known-answer tests (NIST vectors) (push) Waiting to run
contracts-ci / Coverage (scoped, with artifacts) (push) Waiting to run
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:37 +03:00

55 lines
2.4 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
interface IAereFalcon512Verifier {
function verifySignedMessage(bytes calldata pk, bytes calldata sm) external pure returns (bool);
}
/**
* @title RealFalcon512PrecompileAdapter, TEST-ONLY real-crypto stand-in for the 0x0AE1 precompile
*
* @notice Hardhat has no native PQC precompile. Where MockPQCPrecompile models the precompile's
* SEMANTICS (accept iff a keccak commitment matches), this adapter runs ACTUAL Falcon-512
* verification: install it at 0x0AE1 via hardhat_setCode and every registry precompile
* staticcall (`pk || sm`) is routed into the audited, NIST-KAT-proven AereFalcon512Verifier
* (see AereFalcon512Verifier.test.js, which accepts the official round-3 KAT vector 0).
*
* The precompile wire format is IDENTICAL to the live mainnet precompile and to what
* AerePQCKeyRegistry / AerePQCThreshold build:
* input = pk(897) || sm , sm = sigLen(2, big-endian) || nonce(40) || message || esig
* so a positive result here proves the registry assembled the input at the exact NIST
* offsets AND that a genuine Falcon-512 signature (not a mock commitment) is accepted. The
* raw 32-byte return word (0x..01 / 0x..00) matches the live precompile byte layout, so the
* caller's `ret.length >= 32 && ret[31] == 0x01` check behaves exactly as on chain 2800.
*
* The immutable verifier address is baked into runtime bytecode, so it survives the
* hardhat_setCode copy to 0x0AE1.
*/
contract RealFalcon512PrecompileAdapter {
address public immutable verifier;
uint256 internal constant PK_LEN = 897; // Falcon-512 public key length
constructor(address _verifier) {
verifier = _verifier;
}
fallback() external {
bool valid = _check(msg.data);
bytes32 w = valid ? bytes32(uint256(1)) : bytes32(0);
assembly {
mstore(0x0, w)
return(0x0, 32)
}
}
function _check(bytes calldata input) internal view returns (bool) {
if (input.length <= PK_LEN) return false;
bytes calldata pk = input[0:PK_LEN];
bytes calldata sm = input[PK_LEN:];
(bool ok, bytes memory ret) = verifier.staticcall(
abi.encodeWithSelector(IAereFalcon512Verifier.verifySignedMessage.selector, pk, sm)
);
return ok && ret.length >= 32 && abi.decode(ret, (bool));
}
}