diff --git a/.gitmodules b/.gitmodules index 3077b9e..a6ce08d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "solidity/lib/forge-std"] path = solidity/lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "solidity/lib/account-abstraction"] + path = solidity/lib/account-abstraction + url = https://github.com/eth-infinitism/account-abstraction diff --git a/solidity/falcon/deterministic_ecdsa_sign.js b/solidity/falcon/deterministic_ecdsa_sign.js new file mode 100644 index 0000000..96956aa --- /dev/null +++ b/solidity/falcon/deterministic_ecdsa_sign.js @@ -0,0 +1,71 @@ +// first install npm install ethers +import { Wallet, hashMessage, recoverAddress, SigningKey, sha256 } from "ethers"; + +// --- Get arguments from command line --- +// Expected usage: node your_script_name.js <32_byte_seed_hex> +const args = process.argv.slice(2); // Slice to get only the actual arguments + +if (args.length < 2) { + console.error("Usage: node your_script_name.js <32_byte_seed_hex> "); + process.exit(1); +} + +const deterministicSeedInput = args[0]; +const message = args[1]; // The message is now taken directly from the second argument + +// Validate seed length (must be 32 bytes = 64 hex characters) +if (deterministicSeedInput.length !== 64 || !/^[0-9a-fA-F]{64}$/.test(deterministicSeedInput)) { + console.error("Error: Seed must be a 32-byte (64 hex characters) hexadecimal string."); + process.exit(1); +} + +// Prepend "0x" if it's not there, as ethers.sha256 typically expects it or a Uint8Array +const deterministicSeed = deterministicSeedInput.startsWith("0x") ? deterministicSeedInput : "0x" + deterministicSeedInput; + +async function signMessage() { + // Derive the private key deterministically from the seed using SHA256 + const privateKey = sha256(deterministicSeed); + + // Create a Wallet instance from the derived private key + const wallet = new Wallet(privateKey); + + const messageHash = hashMessage(message); + const signature = await wallet.signMessage(message); + const recoveredAddress = recoverAddress(messageHash, signature); + + // Helper to parse the signature + function parseSignature(signature) { + const sig = signature.startsWith("0x") ? signature.slice(2) : signature; + return { + r: "0x" + sig.slice(0, 64), + s: "0x" + sig.slice(64, 128), + v: parseInt(sig.slice(128, 130), 16), + }; + } + const sig = parseSignature(signature); + + const signingKey = new SigningKey(wallet.privateKey); + const publicKey = signingKey.publicKey; + + // Extract X and Y coordinates from the uncompressed public key + const x = "0x" + publicKey.slice(4, 68); // Slice from index 4 to 68 for X (skipping 0x04 prefix) + const y = "0x" + publicKey.slice(68); // Slice from index 68 to end for Y + + console.log("Message: ", message); + console.log("Input Seed (hex):", deterministicSeedInput); + console.log("Derived Private Key:", privateKey); + console.log("Wallet Address: ", wallet.address); + console.log("Message Hash: ", messageHash); + console.log("Signature: ", signature); + console.log("r (signature): ", sig.r); + console.log("s (signature): ", sig.s); + console.log("v (signature): ", sig.v); + console.log("Public Key (uncompressed):", publicKey); // The full 0x04... key + console.log("Public Key X: ", x); + console.log("Public Key Y: ", y); + console.log("Recovered Addr: ", recoveredAddress); +} + +signMessage(); // Call the async function + +console.log("ending script..."); \ No newline at end of file diff --git a/solidity/falcon/deterministic_falcon_sign.js b/solidity/falcon/deterministic_falcon_sign.js new file mode 100644 index 0000000..9ea623e --- /dev/null +++ b/solidity/falcon/deterministic_falcon_sign.js @@ -0,0 +1,124 @@ +const fs = require('fs'); +const Module = require('./falcon.js'); + +// --- Get arguments from command line --- +// Expected usage: node test_falcon.js <32_byte_seed_hex> +const args = process.argv.slice(2); // Slice to get only the actual arguments + +if (args.length < 2) { + console.error("Usage: node test_falcon.js <32_byte_seed_hex> "); + process.exit(1); +} + +const seedHexInput = args[0]; +const messageHexInput = args[1]; + +// Validate seed length (must be 32 bytes = 64 hex characters) +if (seedHexInput.length !== 64) { + console.error("Error: Seed must be 32 bytes (64 hex characters)."); + process.exit(1); +} + +// Convert seed and message hex strings to Buffers +const seed = Buffer.from(seedHexInput, "hex"); +const message = Buffer.from(messageHexInput.startsWith("0x") ? messageHexInput.slice(2) : messageHexInput, "hex"); + +// --- Main FALCON Module execution --- +Module().then((falcon) => { + const pkLen = 897; + const skLen = 1281; + const sigMaxLen = 690; + const seedLen = 32; // This is now enforced by input validation + + // Allocate memory + const pkPtr = falcon._malloc(pkLen); + const skPtr = falcon._malloc(skLen); + const msgPtr = falcon._malloc(message.length); + const seedPtr = falcon._malloc(seedLen); + + falcon.HEAPU8.set(message, msgPtr); + falcon.HEAPU8.set(seed, seedPtr); + + // Generate keypair using the provided seed + falcon.ccall( + 'crypto_keypair', + 'number', + ['number', 'number', 'number'], + [pkPtr, skPtr, seedPtr] + ); + + console.log("๐Ÿ”‘ Message (hex):", message.toString("hex")); + + // The secretKey and publicKey are extracted from WASM memory. + // Note: The secretKey buffer here might include padding or other data + // depending on how crypto_keypair lays out data. For actual use, + // ensure you know the exact layout if you need to store/retrieve it. + const secretKey = Buffer.from(falcon.HEAPU8.subarray(skPtr, skPtr + skLen)); + console.log("๐Ÿ”‘ Secret Key (hex):", secretKey.toString("hex")); + + const publicKey = Buffer.from(falcon.HEAPU8.subarray(pkPtr, pkPtr + pkLen)); + console.log("๐Ÿ”‘ Public Key (base64):", publicKey.toString("base64")); + console.log("๐Ÿ”‘ Public Key (hex):", publicKey.toString("hex")); + + // Sign the message + const signedMsgMaxLen = message.length + sigMaxLen; + const signedMsgPtr = falcon._malloc(signedMsgMaxLen); + const signedMsgLenPtr = falcon._malloc(8); // 64-bit space + + const signRet = falcon._crypto_sign( + signedMsgPtr, + signedMsgLenPtr, + msgPtr, + BigInt(message.length), + skPtr + ); + + if (signRet !== 0) { + console.error("โŒ Signing failed."); + // Free memory before exiting on error + [pkPtr, skPtr, msgPtr, seedPtr, signedMsgPtr, signedMsgLenPtr].forEach(ptr => falcon._free(ptr)); + return; + } + + // Read 64-bit signature length (low + high) + function readUint64(ptr) { + const low = falcon.HEAPU32[ptr >> 2]; + const high = falcon.HEAPU32[(ptr >> 2) + 1]; + return BigInt(high) << 32n | BigInt(low); + } + + const sigLen = Number(readUint64(signedMsgLenPtr)); + const signedMessage = Buffer.from(falcon.HEAPU8.subarray(signedMsgPtr, signedMsgPtr + sigLen)); + + console.log("โœ… Signature generated."); + console.log("๐Ÿ” Sig+Msg (base64):", signedMessage.toString("base64")); + console.log("๐Ÿ” Sig+Msg (hexa):", signedMessage.toString("hex")); + + // Verify the message + const recoveredMsgPtr = falcon._malloc(sigLen); // Max length of recovered message is sigLen (signed message length) + const recoveredLenPtr = falcon._malloc(8); + + const verifyRet = falcon._crypto_sign_open( + recoveredMsgPtr, + recoveredLenPtr, + signedMsgPtr, + BigInt(sigLen), + pkPtr + ); + + if (verifyRet === 0) { + const recLen = Number(readUint64(recoveredLenPtr)); + const recoveredMessage = Buffer.from(falcon.HEAPU8.subarray(recoveredMsgPtr, recoveredMsgPtr + recLen)); + console.log("โœ… Verification success."); + console.log("๐Ÿ“ฆ Recovered message (hex):", recoveredMessage.toString("hex")); + console.log("๐Ÿงช Match:", message.equals(recoveredMessage)); + } else { + console.error("โŒ Signature verification failed."); + } + + // Free memory + [pkPtr, skPtr, msgPtr, seedPtr, signedMsgPtr, signedMsgLenPtr, recoveredMsgPtr, recoveredLenPtr] + .forEach(ptr => falcon._free(ptr)); +}).catch(error => { + console.error("An error occurred during FALCON module initialization or execution:", error); +}); diff --git a/solidity/falcon/test_falcon.js b/solidity/falcon/test_falcon.js index 208212d..9ef95c4 100644 --- a/solidity/falcon/test_falcon.js +++ b/solidity/falcon/test_falcon.js @@ -7,9 +7,13 @@ Module().then((falcon) => { const sigMaxLen = 690; const seedLen= 32; - const message = Buffer.from("hello from ZKNOX!"); const seed=Buffer.from("12345678123456781234567812345679") + const hexString = "0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750"; + + // Remove the "0x" prefix before passing to Buffer.from + const message = Buffer.from(hexString.slice(2), "hex"); + // Allocate memory const pkPtr = falcon._malloc(pkLen); const skPtr = falcon._malloc(skLen); diff --git a/solidity/lib/account-abstraction b/solidity/lib/account-abstraction new file mode 160000 index 0000000..cc3893b --- /dev/null +++ b/solidity/lib/account-abstraction @@ -0,0 +1 @@ +Subproject commit cc3893bcaf2272c163ce89d5eb9eadb8e6b52db7 diff --git a/solidity/lib/kernel b/solidity/lib/kernel new file mode 160000 index 0000000..cd697c7 --- /dev/null +++ b/solidity/lib/kernel @@ -0,0 +1 @@ +Subproject commit cd697c7e21715d015e0643af22310a99aa17433b diff --git a/solidity/script/DelegationExample.s.sol b/solidity/script/DelegationExample.s.sol index a59a370..128abd6 100644 --- a/solidity/script/DelegationExample.s.sol +++ b/solidity/script/DelegationExample.s.sol @@ -105,7 +105,8 @@ contract SignDelegationTest is BaseScript { address iVerifier_algo = address(falcon); address iPublicKey = DeployPolynomial(salty, pkc); - Verifier = new ZKNOX_Verifier(iAlgoID, iVerifier_algo, iPublicKey); + Verifier = new ZKNOX_Verifier(); + Verifier.initialize(iAlgoID, iVerifier_algo, iPublicKey); console.log("param Verifier:", Verifier.algoID(), Verifier.CoreAddress(), Verifier.authorizedPublicKey()); // Deploy an ERC-20 token contract where Alice is the minter. diff --git a/solidity/src/ZKNOX_ZeroDev_Kernel_Module.sol b/solidity/src/ZKNOX_ZeroDev_Kernel_Module.sol new file mode 100644 index 0000000..032d7c2 --- /dev/null +++ b/solidity/src/ZKNOX_ZeroDev_Kernel_Module.sol @@ -0,0 +1,214 @@ +/** + * + */ +/*ZZZZZZZZZZZZZZZZZZZKKKKKKKKK KKKKKKKNNNNNNNN NNNNNNNN OOOOOOOOO XXXXXXX XXXXXXX ..../&@&#. .###%@@@#, .. +/*Z:::::::::::::::::ZK:::::::K K:::::KN:::::::N N::::::N OO:::::::::OO X:::::X X:::::X ...(@@* .... . &#//%@@&,. +/*Z:::::::::::::::::ZK:::::::K K:::::KN::::::::N N::::::N OO:::::::::::::OO X:::::X X:::::X ..*@@......... .@#%%(%&@&.. +/*Z:::ZZZZZZZZ:::::Z K:::::::K K::::::KN:::::::::N N::::::NO:::::::OOO:::::::OX::::::X X::::::X .*@( ........ . .&@@@@. .@%%%%%#&@@. +/*ZZZZZ Z:::::Z KK::::::K K:::::KKKN::::::::::N N::::::NO::::::O O::::::OXXX:::::X X::::::XX ...&@ ......... . &. .@ /@%%%%%%&@@# +/* Z:::::Z K:::::K K:::::K N:::::::::::N N::::::NO:::::O O:::::O X:::::X X:::::X ..@( .......... . &. ,& /@%%%%&&&&@@@. +/* Z:::::Z K::::::K:::::K N:::::::N::::N N::::::NO:::::O O:::::O X:::::X:::::X ..&% ........... .@%(#@# ,@%%%%&&&&&@@@%. +/* Z:::::Z K:::::::::::K N::::::N N::::N N::::::NO:::::O O:::::O X:::::::::X ..,@ ............ *@%%%&%&&&&&&@@@. +/* Z:::::Z K:::::::::::K N::::::N N::::N:::::::NO:::::O O:::::O X:::::::::X ..(@ ............. ,#@&&&&&&&&&&&&@@@@* +/* Z:::::Z K::::::K:::::K N::::::N N:::::::::::NO:::::O O:::::O X:::::X:::::X .*@.............. . ..,(%&@@&&&&&&&&&&&&&&&&@@@@, +/* Z:::::Z K:::::K K:::::K N::::::N N::::::::::NO:::::O O:::::O X:::::X X:::::X ...&#............. *@@&&&&&&&&&&&&&&&&&&&&@@&@@@@& +/*ZZZ:::::Z ZZZZZKK::::::K K:::::KKKN::::::N N:::::::::NO::::::O O::::::OXXX:::::X X::::::XX ...@/.......... *@@@@. ,@@. &@&&&&&&@@@@@@@@@@@. +/*Z::::::ZZZZZZZZ:::ZK:::::::K K::::::KN::::::N N::::::::NO:::::::OOO:::::::OX::::::X X::::::X ....&#..........@@@, *@@&&&@% .@@@@@@@@@@@@@@@& +/*Z:::::::::::::::::ZK:::::::K K:::::KN::::::N N:::::::N OO:::::::::::::OO X:::::X X:::::X ....*@.,......,@@@...@@@@@@&..%@@@@@@@@@@@@@/ +/*Z:::::::::::::::::ZK:::::::K K:::::KN::::::N N::::::N OO:::::::::OO X:::::X X:::::X ...*@,,.....%@@@,.........%@@@@@@@@@@@@( +/*ZZZZZZZZZZZZZZZZZZZKKKKKKKKK KKKKKKKNNNNNNNN NNNNNNN OOOOOOOOO XXXXXXX XXXXXXX ...&@,....*@@@@@ ..,@@@@@@@@@@@@@&. +/* ....,(&@@&..,,,/@&#*. . +/* ......(&.,.,,/&@,. +/* .....,%*.,*@% +/* .#@@@&(&@*,,*@@%,.. +/* .##,,,**$.,,*@@@@@%. +/* *(%%&&@(,,**@@@@@& +/* . . .#@((@@(*,** +/* . (*. . +/* .*/ +///* Copyright (C) 2025 - Renaud Dubois, Simon Masson - This file is part of ZKNOX project +///* License: This software is licensed under MIT License +///* This Code may be reused including this header, license and copyright notice. +///* See LICENSE file at the root folder of the project. +///* FILE: ZKNOX_falcon.sol +///* Description: Compute NIST compliant falcon verification +/** + * + */ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import {IEntryPoint} from "../lib/account-abstraction/contracts/interfaces/IEntryPoint.sol"; +import "./ZKNOX_HashToPoint.sol"; + +import "./ZKNOX_IVerifier.sol"; +import "./ZKNOX_common.sol"; +import "./ZKNOX_falcon_core.sol"; + +//choose the XOF to use here +import "./ZKNOX_falcon_encodings.sol"; +import "./ZKNOX_falcon_utils.sol"; + +import { console } from "forge-std/Test.sol"; +import {IValidator} from "../lib/kernel/src/interfaces/IERC7579Modules.sol"; + +import {SIG_VALIDATION_SUCCESS_UINT, SIG_VALIDATION_FAILED_UINT} from "../lib/kernel/src/types/Constants.sol"; +import {ZKNOX_NTT} from "./ZKNOX_NTT.sol"; +import {PackedUserOperation} from "../lib/kernel/src/interfaces/PackedUserOperation.sol"; + +/// @notice Contract designed for being delegated to by EOAs to authorize a IVerifier key to transact on their behalf. +contract ZKNOX_ZeroDev_Kernel_Module is IValidator { + + // TODO: remove after testing + function helloWorld() external { + console.log("hello world!"); + } + + error InvalidCaller(); + + bytes32 constant SIMPLEHYBRID7702_STORAGE_POSITION = keccak256("zknox.hybrid.7702"); + + // address of entryPoint v0.8 + function entryPoint() public pure returns (IEntryPoint) { + return IEntryPoint(0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108); + } + + struct Storage { + //derived address from ecdsa + address authorized_ECDSA; + + /// @notice Address of the contract storing the post quantum public key + address authorized_PQPublicKey; + /// @notice Address of the verification contract logic + + address CoreAddress; //address of the core verifier (FALCON, DILITHIUM, etc.), shall be the address of a ISigVerifier + uint256 algoID; + } + + function getStorage() internal pure returns (Storage storage ds) { + bytes32 position = SIMPLEHYBRID7702_STORAGE_POSITION; + assembly { + ds.slot := position + } + } + + constructor() {} + + //input are AlgoIdentifier, Signature verification address, publickey storing contract + function initialize(uint256 iAlgoID, address iCore, address iAuthorized_ECDSA, address iPublicPQKey) external { + /* TODO: uncomment! + if (msg.sender != address(entryPoint().senderCreator())) { + revert InvalidCaller(); + } + */ + if (getStorage().CoreAddress != address(0)) { + revert AlreadyInitialized(iPublicPQKey); + } + + getStorage().authorized_ECDSA=iAuthorized_ECDSA; //derived address from ecdsa secp256K1 + getStorage().CoreAddress = iCore; // Address of contract of Signature verification (FALCON, DILITHIUM) + getStorage().algoID = iAlgoID; + getStorage().authorized_PQPublicKey = iPublicPQKey; + } + + function _validateSignature( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) internal virtual returns (uint256 validationData) { + (uint8 v, bytes32 r, bytes32 s, bytes memory sm) = abi.decode(userOp.signature, (uint8, bytes32, bytes32, bytes)); + bytes32 h = 0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750;//the hash signed by FALCON NIST and ECDSA, provided by etherjs for ECDSA and test_falcon.js for falcon + +// TODO: the plan is to use EIP-191 message hash as input of both ECDSA and Falcon +// bytes message = abi.encodePacked("\x19Ethereum Signed Message:\n", userOpHash); +// bytes32 h1 = keccak256(message); +// return isValid(userOpHash, v, r, s, sm) ? SIG_VALIDATION_SUCCESS_UINT : SIG_VALIDATION_FAILED_UINT; + return isValid(h, v, r, s, sm) ? SIG_VALIDATION_SUCCESS_UINT : SIG_VALIDATION_FAILED_UINT; + } + + + //digest, v,r,s are input to ecrecover, sm is the falcon signature + //TODO : do not revert - kept for hackathon + function isValid( + bytes32 digest, + uint8 v, + bytes32 r, + bytes32 s, + bytes memory sm // the signature in the NIST KAT format, as output by test_falcon.js + ) public returns (bool) + { + uint256 slen = (uint256(uint8(sm[0])) << 8) + uint256(uint8(sm[1])); + uint256 mlen = sm.length - slen - 42; + + bytes memory message; + bytes memory salt = new bytes(40); + + for (uint i = 0; i < 40; i++) { + salt[i] = sm[i + 2]; + } + message = new bytes(mlen); + for (uint256 j = 0; j < mlen; j++) { + message[j] = sm[j + 42]; + } + + if (sm[2 + 40 + mlen] != 0x29) { + revert("wrong header sigbytes"); + } + + uint256[] memory s2 =_ZKNOX_NTT_Compact((_decompress_sig(sm, 2 + 40 + mlen + 1))); + + ISigVerifier Core = ISigVerifier(getStorage().CoreAddress); + + uint256[] memory nttpk; + address recovered = ecrecover(digest, v, r, s); + + require(getStorage().authorized_PQPublicKey != address(0), "authorizedPublicKey null"); + require(recovered==getStorage().authorized_ECDSA, "Invalid ECDSA signature"); + nttpk = Core.GetPublicKey(getStorage().authorized_PQPublicKey); + require(Core.verify(abi.encodePacked(digest), salt, s2, nttpk), "Invalid FALCON"); + + return true; + } + + + + function GetPublicKey() public view returns (uint256[] memory res) { + ISigVerifier Core = ISigVerifier(getStorage().CoreAddress); + res = Core.GetPublicKey(getStorage().authorized_PQPublicKey); + } + + function GetStorage() public view returns (address, address) { + return (getStorage().CoreAddress, getStorage().authorized_PQPublicKey); + } + + function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) + external + payable + returns (uint256) { + console.log("INSIDE THE validateUserOp OF THE CUSTOM MODULE"); + return _validateSignature(userOp, userOpHash); + } + + function isValidSignatureWithSender(address sender, bytes32 hash, bytes calldata data) + external + view + returns (bytes4) { + return 0xffffffff; + } + + function onInstall(bytes calldata data) external payable { + + } + + function onUninstall(bytes calldata data) external payable { + + } + + function isModuleType(uint256 moduleTypeId) external view returns (bool) { + return true; + } + + function isInitialized(address smartAccount) external view returns (bool) { + return true; + } + //receive() external payable {} +} //end contract diff --git a/solidity/src/ZKNOX_delegate_noproxy.sol b/solidity/src/ZKNOX_delegate_noproxy.sol index 22de288..256d878 100644 --- a/solidity/src/ZKNOX_delegate_noproxy.sol +++ b/solidity/src/ZKNOX_delegate_noproxy.sol @@ -52,8 +52,11 @@ contract ZKNOX_Verifier { /// @notice Internal nonce used for replay protection, must be tracked and included into prehashed message. uint256 public nonce; + constructor() {} + //input are AlgoIdentifier, Signature verification address, publickey storing contract - constructor(uint256 iAlgoID, address iCore, address iPublicKey) { + function initialize(uint256 iAlgoID, address iCore, address iPublicKey) external { + require(CoreAddress == address(0), "already initialized"); CoreAddress = iCore; // Address of contract of Signature verification (FALCON, DILITHIUM) algoID = iAlgoID; authorizedPublicKey = iPublicKey; @@ -74,7 +77,8 @@ contract ZKNOX_Verifier { uint256[] memory nttpk; require(authorizedPublicKey != address(0), "authorizedPublicKey null"); - //nttpk = Core.GetPublicKey(authorizedPublicKey); + nttpk = Core.GetPublicKey(authorizedPublicKey); + require(nttpk[0]!=0, "wrong extraction"); //require(Core.verify(abi.encodePacked(digest), salt, s2, nttpk), "Invalid signature"); (bool success,) = to.call{value: val}(data); @@ -83,11 +87,11 @@ contract ZKNOX_Verifier { } //debug function for now: todo, remove when transact successfully tested - function verify( + function isValid( bytes memory data, bytes memory salt, // compacted signature salt part uint256[] memory s2 - ) public view returns (bool) { + ) external payable returns (bool) { ISigVerifier Core = ISigVerifier(CoreAddress); uint256[] memory nttpk; nttpk = Core.GetPublicKey(authorizedPublicKey); diff --git a/solidity/src/ZKNOX_falcon_deploy.sol b/solidity/src/ZKNOX_falcon_deploy.sol index ec37219..f9dc8a6 100644 --- a/solidity/src/ZKNOX_falcon_deploy.sol +++ b/solidity/src/ZKNOX_falcon_deploy.sol @@ -38,6 +38,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; + + function _Swap16(uint256 inw) pure returns (uint256 outw) { for (uint256 i = 0; i < 256; i += 16) { outw ^= (inw >> (240 - i) & 0xffff) << (i); @@ -116,3 +118,4 @@ function DeployPolynomial(bytes32 salt, uint256[] memory polynomial) returns (ad } require(a_polynomial != address(0), "Deployment failed"); } + diff --git a/solidity/src/ZKNOX_falcon_encodings.sol b/solidity/src/ZKNOX_falcon_encodings.sol index 23f1830..0e213f1 100644 --- a/solidity/src/ZKNOX_falcon_encodings.sol +++ b/solidity/src/ZKNOX_falcon_encodings.sol @@ -36,7 +36,9 @@ * */ import "./ZKNOX_falcon_utils.sol"; -//import {Test, console} from "forge-std/Test.sol"; + +import "./ZKNOX_NTT.sol"; +import "./ZKNOX_NTT_falcon.sol"; uint256 constant max_in_len = 666; @@ -189,3 +191,25 @@ function decompress_KAT(bytes memory pk, bytes memory sm) return (h, s2, salt, message); } + + +//deploy a polynomial onchain from the NIST encoding +function DeployPolynomial_NIST(bytes32 salt, bytes memory pk) returns (address a_polynomial) { + + /* + * Decode public key. + */ + if (pk[0] != 0x09) { + revert("wrong public key encoding"); + } + uint256[] memory polynomial = decompress_kpub(pk, 1); + polynomial=_ZKNOX_NTT_Compact(_ZKNOX_NTTFW_vectorized(polynomial)); + + bytes memory bytecode_pol = abi.encodePacked(polynomial); + + bytecode_pol = abi.encodePacked(hex"63", uint32(bytecode_pol.length), hex"80600E6000396000F3", bytecode_pol); + assembly { + a_polynomial := create2(0, add(bytecode_pol, 0x20), mload(bytecode_pol), salt) + } + require(a_polynomial != address(0), "Deployment failed"); +} \ No newline at end of file diff --git a/solidity/src/ZKNOX_hybrid.sol b/solidity/src/ZKNOX_hybrid.sol index 918ef4b..5bcf999 100644 --- a/solidity/src/ZKNOX_hybrid.sol +++ b/solidity/src/ZKNOX_hybrid.sol @@ -47,7 +47,7 @@ import "./ZKNOX_falcon_core.sol"; //choose the XOF to use here import "./ZKNOX_HashToPoint.sol"; - +import "./ZKNOX_falcon_encodings.sol"; /// @notice Contract designed for being delegated to by EOAs to authorize a IVerifier key to transact on their behalf. contract ZKNOX_HybridVerifier { @@ -64,61 +64,53 @@ contract ZKNOX_HybridVerifier { /// @notice Internal nonce used for replay protection, must be tracked and included into prehashed message. uint256 public nonce; + constructor() {} + //input are AlgoIdentifier, Signature verification address, publickey storing contract - constructor(uint256 iAlgoID, address iCore, address iPublicPQKey) { + function initialize(uint256 iAlgoID, address iCore, address iAuthorized_ECDSA, address iPublicPQKey) external { + require(CoreAddress == address(0), "already initialized"); + + authorized_ECDSA=iAuthorized_ECDSA; //derived address from ecdsa secp256K1 CoreAddress = iCore; // Address of contract of Signature verification (FALCON, DILITHIUM) algoID = iAlgoID; authorized_PQPublicKey = iPublicPQKey; nonce = 0; } - /// @notice Main entrypoint for authorized transactions. Accepts transaction parameters (to, data, value) and a musig2 signature. - function transact( - address to, - bytes memory data, - uint256 val, - + //digest, v,r,s are input to ecrecover, sm is the falcon signature + function isValid( + bytes32 digest, uint8 v, bytes32 r, bytes32 s, - bytes memory salt, // compacted FALCONsignature salt part - uint256[] memory s2 // compacted FALCON signature s2 part) - ) external payable { - bytes32 digest = keccak256(abi.encode(nonce++, to, data, val)); - ISigVerifier Core = ISigVerifier(CoreAddress); - - uint256[] memory nttpk; - address recovered = ecrecover(digest, v, r, s); - + bytes memory sm // the signature in the NIST KAT format, as output by test_falcon.js + ) public returns (bool) + { + uint256 slen = (uint256(uint8(sm[0])) << 8) + uint256(uint8(sm[1])); + uint256 mlen = sm.length - slen - 42; + + bytes memory message; + bytes memory salt = new bytes(40); + + for (uint i = 0; i < 40; i++) { + salt[i] = sm[i + 2]; + } + message = new bytes(mlen); + for (uint256 j = 0; j < mlen; j++) { + message[j] = sm[j + 42]; + } - require(authorized_PQPublicKey != address(0), "authorizedPublicKey null"); - require(recovered==authorized_ECDSA, "Invalid ECDSA signature"); - //nttpk = Core.GetPublicKey(authorized_PQPublicKey); - //require(Core.verify(abi.encodePacked(digest), salt, s2, nttpk), "Invalid FALCON"); + if (sm[2 + 40 + mlen] != 0x29) { + revert("wrong header sigbytes"); + } - (bool success,) = to.call{value: val}(data); + uint256[] memory s2 =_ZKNOX_NTT_Compact((_decompress_sig(sm, 2 + 40 + mlen + 1))); - require(success, "failing executing the cal"); - } - - function isValid_HybridSignature( - address to, - bytes memory data, - uint256 val, - uint8 v, - bytes32 r, - bytes32 s, - bytes memory salt, // compacted FALCONsignature salt part - uint256[] memory s2 // compacted FALCON signature s2 part)) - ) public returns (bool) - { - bytes32 digest = keccak256(abi.encode(nonce++, to, data, val)); ISigVerifier Core = ISigVerifier(CoreAddress); uint256[] memory nttpk; address recovered = ecrecover(digest, v, r, s); - require(authorized_PQPublicKey != address(0), "authorizedPublicKey null"); require(recovered==authorized_ECDSA, "Invalid ECDSA signature"); nttpk = Core.GetPublicKey(authorized_PQPublicKey); @@ -129,18 +121,6 @@ contract ZKNOX_HybridVerifier { - //debug function for now: todo, remove when transact successfully tested - function verify( - bytes memory data, - bytes memory salt, // compacted signature salt part - uint256[] memory s2 - ) public view returns (bool) { - ISigVerifier Core = ISigVerifier(CoreAddress); - uint256[] memory nttpk; - nttpk = Core.GetPublicKey(authorized_PQPublicKey); - return Core.verify(data, salt, s2, nttpk); - } - function GetPublicKey() public view returns (uint256[] memory res) { ISigVerifier Core = ISigVerifier(CoreAddress); res = Core.GetPublicKey(authorized_PQPublicKey); diff --git a/solidity/test/ZKNOX_IVerifierDelegate_noproxy.t.sol b/solidity/test/ZKNOX_IVerifierDelegate_noproxy.t.sol index 2b34e60..e64540c 100644 --- a/solidity/test/ZKNOX_IVerifierDelegate_noproxy.t.sol +++ b/solidity/test/ZKNOX_IVerifierDelegate_noproxy.t.sol @@ -92,7 +92,7 @@ contract SignDelegationTest is Test { falcon = new ZKNOX_ethfalcon(); // public key in ntt form // forgefmt: disable-next-line - uint256[32] memory tmp_pkc = [20377218425118340445148364134355217251962993606936992273331839780054216280849, 20121106827228450321124896615938334719918113760150351437528659189176262990636, 10067497595444039977213793634597611854404700659079271442444950951559432116521, 8117003418140413121709569530562717039471558017795389997976077490386494167285, 19719916617578783495479977733846345663822541355599584111604787561804371332299, 12011255695358364119082992510081379197681548345148896992583517862986064267371, 1413712800155248155901989741415704580119744515670156265477932184210522442954, 20205896941262413308936850117551422118594142119900192427257346204109575433582, 3486279541225130755598501027003998051985801747561740177288468626060198090459, 15477599456049069393051346514952035991054078301113692636739851820730251809819, 21156392022423827010876847021244058034030321298933336763476969617428294271271, 2908341131797448574919302622375649436059983246466303686691800726354050296280, 4014285105619800009931504325676093765338451832744274077688243007139640906463, 17525386234073442601006363277175078033276096227970594283065994928074709206070, 9399682681199319758356271164177409471029167726563817053939019373865509324066, 14497266053893643950060558685941531408969726991430751449270004178102628913394, 20001018922134128765022849593872125843127919031255693298563962888117505231302, 20223399471737868067964408671262891234552388541376818065834177454291358723391, 11076429199706617732593752467897544427206591530047673604493842949459150906661, 10003914827585439734433133640025401879385317162577084551224105445404031001782, 20818841785974240140489196577114322827962289517719106191109136290716168037702, 9930008312479770233251082269305959959461466299666759427058224003186584853639, 13961923764749961571138036653552925829425897028586292322709756121414948556716, 1865847632959804051511238296007895164923970314748517688837335778369740540589, 9619029050213147645610307806665071441731316717663787766260527940528214317525, 14242850992292404983847270889619711734347852346434510691917062411771622728876, 14741088360075140317883502213566092308263093099494020005957065598182206670698, 450741599221347172965973222014483009289616792068532398266398440365899262013, 18781682460599299134542238039348179607304289110944838378016618837639364477280, 9945663145577743462232497392336568635199398547866845488457561121052707133988, 4434915596203863112439022225522412087141907977885194617923870370615952742502, 9078099396363096043342272050200561246179429816170715912419583083116430298211]; + uint256[32] memory tmp_pkc = [5662797900309780854973796610500849947334657117880689816302353465126500706865, 19773102689601973621062070293263100534733440101750387150077711329493973274058, 14606681890476865709816748627007131256488820167404174518724605890405097603719, 15845234755931409677594030697035096324340457247480758851130851814703350289524, 5524941775098342886171484209767745714294893760953145782448900256027476885810, 15301033023652038200658165594502048003364566882283859976805808429697192567788, 18875246040654000517074755552890901133645669291006567534900678519700207707731, 11843395683334522200668269515783436692309636627649985746204914551011013629864, 8419305811746464065544475584323153271481428319969733938911379662274846467111, 18343417927809591481517183183479503623951147924071925629514120039495430967592, 10007451325105194000131443764495043320645967197761209321537835667210153693191, 779487061150515667795843171268512499191273448454307717194241961063365614179, 14889466660684110621550004892629051623956217990147793956971155241422811501259, 2995124819739638247263964985959552967489690950312509006670204449438399867779, 16698797261630410217796026169071784061995015858612862963622742163763641855864, 13129716852402613948762495927854872029721399215764359316540986925328111906305, 8620514528683669238836845045565231437047299941974001946945409334379184590766, 5184181041252042291984928267300200431567362250531180743278111084485128161037, 15555356690664302555826193017277818624355238475260445618945780405430020481200, 19264077329172342356817033544893125657281034846341493111114385757819435942150, 8708853592016768361541207473719404660232059936330605270802350059910738161396, 21018648773068189736719755689803981281912117625241701774409626083005150670687, 267026197077955750670312407002345619518873569178283514941902712705828521229, 14359242962640593260752841229079220345384234239741953227891227234975247894859, 8320354099602406351863744856415421903486499003224102136141447162113864442068, 17564344674783852357247325589247473882830766139750808683064015010041459773180, 12601232530472338126510941067000966999586933909071534455578397454667291628041, 17820703520112071877812607241017358905719406745793395857586668204300579510382, 20977963461796112341763752649093803701879441191599296283127418471622134932903, 5627732773047409045458881938100601008133088383905060686572856121439798106767, 2602661464000108367786729796742170641292899005030508211661215565063118195399, 20110282897068872581106488251090599973196923955248066799683528955504800771309]; uint256[] memory pkc = ZKNOX_memcpy32(tmp_pkc); uint256 iAlgoID = FALCONSHAKE_ID; @@ -101,14 +101,22 @@ contract SignDelegationTest is Test { address iVerifier_algo = address(falcon); address iPublicKey = DeployPolynomial(salty, pkc); - Verifier = new ZKNOX_Verifier(iAlgoID, iVerifier_algo, iPublicKey); - console.log("param Verifier:", Verifier.algoID(), Verifier.CoreAddress(), Verifier.authorizedPublicKey()); + Verifier = new ZKNOX_Verifier(); + + // Alice signs a delegation allowing `implementation` to execute transactions on her behalf. + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(Verifier), ALICE_PK); + + vm.attachDelegation(signedDelegation); + ZKNOX_Verifier aliceVerifier = ZKNOX_Verifier(ALICE_ADDRESS); + aliceVerifier.initialize(iAlgoID, iVerifier_algo, iPublicKey); + console.log("param Verifier:", aliceVerifier.algoID(), aliceVerifier.CoreAddress(), aliceVerifier.authorizedPublicKey()); // Deploy an ERC-20 token contract where Alice is the minter. token = new ERC20(ALICE_ADDRESS); } - function test_SimpDeg() public { + //test vector is + function test_SimpDeg_prague() public { // Construct a single transaction call: Mint 100 tokens to Bob. //SimpleDelegateContract.Call[] memory calls = new SimpleDelegateContract.Call[](1); bytes memory data = abi.encodeCall(ERC20.mint, (100, BOB_ADDRESS)); @@ -133,16 +141,6 @@ contract SignDelegationTest is Test { //calls[0] = SimpleDelegateContract.Call({to: address(token), data: data, value: 0}); vm.startBroadcast(ALICE_PK); - // Alice signs a delegation allowing `implementation` to execute transactions on her behalf. - Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(Verifier), ALICE_PK); - - // Set Alice's storage before calling Verifier - - vm.store(ALICE_ADDRESS, bytes32(uint256(0)), bytes32(uint256(uint160(Verifier.authorizedPublicKey())))); - vm.store(ALICE_ADDRESS, bytes32(uint256(1)), bytes32(uint256(uint160(Verifier.CoreAddress())))); - vm.store(ALICE_ADDRESS, bytes32(uint256(2)), bytes32(Verifier.algoID())); - vm.store(ALICE_ADDRESS, bytes32(uint256(3)), bytes32(Verifier.nonce())); - // Debug: Print stored values to verify correct setup console.log( @@ -159,7 +157,6 @@ contract SignDelegationTest is Test { vm.stopBroadcast(); vm.broadcast(BOB_PK); - vm.attachDelegation(signedDelegation); bytes memory code = address(ALICE_ADDRESS).code; //this shall be ef0100, followed by adress console.log("Verifier address:%x", uint256(uint160(address(Verifier)))); @@ -176,4 +173,59 @@ contract SignDelegationTest is Test { // Verify Bob successfully received 100 tokens. vm.assertEq(token.balanceOf(BOB_ADDRESS), 100); } -} + + + function testVector0_prague() public { + // public key + // forgefmt: disable-next-line + uint256[32] memory tmp_pkc = [5662797900309780854973796610500849947334657117880689816302353465126500706865, 19773102689601973621062070293263100534733440101750387150077711329493973274058, 14606681890476865709816748627007131256488820167404174518724605890405097603719, 15845234755931409677594030697035096324340457247480758851130851814703350289524, 5524941775098342886171484209767745714294893760953145782448900256027476885810, 15301033023652038200658165594502048003364566882283859976805808429697192567788, 18875246040654000517074755552890901133645669291006567534900678519700207707731, 11843395683334522200668269515783436692309636627649985746204914551011013629864, 8419305811746464065544475584323153271481428319969733938911379662274846467111, 18343417927809591481517183183479503623951147924071925629514120039495430967592, 10007451325105194000131443764495043320645967197761209321537835667210153693191, 779487061150515667795843171268512499191273448454307717194241961063365614179, 14889466660684110621550004892629051623956217990147793956971155241422811501259, 2995124819739638247263964985959552967489690950312509006670204449438399867779, 16698797261630410217796026169071784061995015858612862963622742163763641855864, 13129716852402613948762495927854872029721399215764359316540986925328111906305, 8620514528683669238836845045565231437047299941974001946945409334379184590766, 5184181041252042291984928267300200431567362250531180743278111084485128161037, 15555356690664302555826193017277818624355238475260445618945780405430020481200, 19264077329172342356817033544893125657281034846341493111114385757819435942150, 8708853592016768361541207473719404660232059936330605270802350059910738161396, 21018648773068189736719755689803981281912117625241701774409626083005150670687, 267026197077955750670312407002345619518873569178283514941902712705828521229, 14359242962640593260752841229079220345384234239741953227891227234975247894859, 8320354099602406351863744856415421903486499003224102136141447162113864442068, 17564344674783852357247325589247473882830766139750808683064015010041459773180, 12601232530472338126510941067000966999586933909071534455578397454667291628041, 17820703520112071877812607241017358905719406745793395857586668204300579510382, 20977963461796112341763752649093803701879441191599296283127418471622134932903, 5627732773047409045458881938100601008133088383905060686572856121439798106767, 2602661464000108367786729796742170641292899005030508211661215565063118195399, 20110282897068872581106488251090599973196923955248066799683528955504800771309]; + uint256[] memory pkc = ZKNOX_memcpy32(tmp_pkc); + + // signature s2 + // forgefmt: disable-next-line + uint256[32] memory tmp_s2 = [189061025430138993865854805011532069333293715869299695949354293295109767338, 309200829492683618362801840838735315073239679824516877254610688296907178015, 17669203565873415420439226729611576544749443656481276334890396524208467774, 21567902685951065342220093337212015325627859479836552266578154972738260959272, 21629742710641854202617034886213873892640485268970955124070672848858167127875, 21518761173595649991077541634911872372568563460460287375282464679909027151878, 88668843202050080354162430362465493400899326659627631899251092744825352121, 21589115041612929508944530253353887521990674352656231997732268725231305949408, 77748037816609010048821043986758852741763365848433569238103440621543948394, 196125604980477431416529085554673976708993318735365421874476849166068940885, 21444227575187532861933165945345576589177205410775875437029272647414716641113, 21571766779137214249890997998635625679180679668367453624699784252197002280960, 132842791722068690864021037096966919030178447937701691660884444009250095184, 252660618073406522895016361327352646221166102604901000414436689373735890818, 21661875898514585455300483231269254543688174841797784277884596070553710964571, 408469887372575727764354863939787898486221033046251585808276641395393310697, 21483098798806565528090561173471573130149923357778077129069435100923827138387, 21365040707017283224032169374693579384647805515287338499452209675962376454353, 139582082355163817792446396090827957258977980096747497728717346717617488024, 21698977390374140751926738932285965733024723476130692021975378126228657012810, 21582043479534721231928031949222680268801040592884446810862621247728671654012, 106016188978695213660006561000087639649638405319762547008619378770056380540, 21396523669988578255532519494435324598773577619532813394543061212841669504837, 567487142710691728457912662951684626851937150493245889102477722465050636084, 185844569086061214504135130584456987157183142589951887136070171885834153901, 350162015184944149647336545709148596957881292049384682934039156939714199637, 56868125263755762880306655715105756108612883350558868787549471782918631255, 113409366200701537080466339400905201724440194357091543728319651397816025091, 598968924407998825190710488524458442266573561012338161932509137359297720206, 21524058349737765174490280399545977619713148567855354072883708688105677467568, 21592968836075103278633512472085925061228035841536899495353847705011755429638, 224400819594214410949880090102269951771459564115310187818733077437072605190]; + uint256[] memory s2 = new uint256[](32); + for (uint256 i = 0; i < 32; i++) { + s2[i] = tmp_s2[i]; + } + // message + bytes memory message = "My name is Renaud"; + bytes memory salt = + "\x46\xb9\xdd\x2b\x0b\xa8\x8d\x13\x23\x3b\x3f\xeb\x74\x3e\xeb\x24\x3f\xcd\x52\xea\x62\xb8\x1b\x82\xb5\x0c\x27\x64\x6e\xd5\x76\x2f\xd7\x5d\xc4\xdd\xd8\xc0\xf2\x00"; + bool result = falcon.verify(message, salt, s2, pkc); + assertEq(true, result); + + vm.startBroadcast(ALICE_PK); + + // Debug: Print stored values to verify correct setup + console.log( + "Stored authorizedPublicKey at Alice:", + address(uint160(uint256(vm.load(ALICE_ADDRESS, bytes32(uint256(0)))))) + ); + console.log( + "Stored CoreAddress at Alice:", address(uint160(uint256(vm.load(ALICE_ADDRESS, bytes32(uint256(1)))))) + ); + console.log("Stored algoID at Alice:", uint256(vm.load(ALICE_ADDRESS, bytes32(uint256(2))))); + console.log("Stored nonce at Alice:", uint256(vm.load(ALICE_ADDRESS, bytes32(uint256(3))))); + + // As Bob, execute the transaction via Alice's temporarily assigned contract. + vm.stopBroadcast(); + + vm.broadcast(BOB_PK); + bytes memory code = address(ALICE_ADDRESS).code; //this shall be ef0100, followed by adress + + console.log("Verifier address:%x", uint256(uint160(address(Verifier)))); + + console.log("code written at eoa Alice:"); + console.logBytes(code); + + // Verify that Alice's account now temporarily behaves as a smart contract. + require(code.length > 0, "no code written to Alice"); + + // As Bob, execute the transaction via Alice's temporarily assigned contract. + bool isValid=ZKNOX_Verifier(ALICE_ADDRESS).isValid(message, salt, s2); //this is the delegation we want, failing now + console.log("signature result:", isValid); + + } + +}//end contract test Delegation diff --git a/solidity/test/ZKNOX_ZeroDev_Kernel_Module.t.sol b/solidity/test/ZKNOX_ZeroDev_Kernel_Module.t.sol new file mode 100644 index 0000000..3fb38de --- /dev/null +++ b/solidity/test/ZKNOX_ZeroDev_Kernel_Module.t.sol @@ -0,0 +1,117 @@ +pragma solidity ^0.8.25; + +import "../lib/account-abstraction/contracts/core/EntryPoint.sol"; + +import {MockValidator} from "../lib/kernel/test/mock/MockValidator.sol"; + +import "../src/ZKNOX_falcon.sol"; +import "../src/ZKNOX_falcon_encodings.sol"; +import "forge-std/Vm.sol"; +import {IEntryPoint as IEntryPointZeroDev} from "../lib/kernel/src/interfaces/IEntryPoint.sol"; +import {IValidator, IHook} from "../lib/kernel/src/interfaces/IERC7579Modules.sol"; +import {InstallValidatorDataFormat, InstallFallbackDataFormat} from "../lib/kernel/src/types/Structs.sol"; +import {Kernel} from "../lib/kernel/src/Kernel.sol"; + +import {MODULE_TYPE_VALIDATOR, MODULE_TYPE_FALLBACK, HOOK_MODULE_NOT_INSTALLED, VALIDATION_TYPE_VALIDATOR, VALIDATION_MODE_DEFAULT, CALLTYPE_SINGLE} from "../lib/kernel/src/types/Constants.sol"; +import {Test, console} from "forge-std/Test.sol"; + +import {ValidationMode, ValidationType, ValidationId} from "../lib/kernel/src/types/Types.sol"; +import {ValidatorLib} from "../lib/kernel/src/utils/ValidationTypeLib.sol"; +import {ZKNOX_ZeroDev_Kernel_Module} from "../src/ZKNOX_ZeroDev_Kernel_Module.sol"; + +uint256 constant ALICE_PK = 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d; +address payable constant ALICE_ADDRESS = payable(0x70997970C51812dc3A010C7d01b50e0d17dc79C8); + +contract ZKNOX_ZeroDev_Kernel_Module_Test is Test { + ZKNOX_ZeroDev_Kernel_Module public module; + Kernel public kernelImplementation; + Kernel public kernelAlice; + EntryPoint public entryPoint; + + function setUp() external { + bytes memory bytecode; + module = new ZKNOX_ZeroDev_Kernel_Module(); + + entryPoint = new EntryPoint(); + kernelImplementation = new Kernel(IEntryPointZeroDev(address(entryPoint))); + kernelAlice = Kernel(ALICE_ADDRESS); + + // Alice signs a delegation allowing `implementation` to execute transactions on her behalf. + vm.deal(ALICE_ADDRESS, 10 ether); + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(kernelImplementation), ALICE_PK); + vm.attachDelegation(signedDelegation); + vm.startBroadcast(ALICE_PK); + module.helloWorld(); + vm.stopBroadcast(); + + bytes memory selectorData = abi.encodePacked(ZKNOX_ZeroDev_Kernel_Module.helloWorld.selector); + InstallValidatorDataFormat memory data = InstallValidatorDataFormat(hex"", hex"", selectorData); + bytes[] memory configs = new bytes[](0); + + // Copied from ZKNOX_hybrid.t.sol + ZKNOX_falcon falcon = new ZKNOX_falcon(); + uint256 iAlgoID = FALCONSHAKE_ID; + bytes32 salty = keccak256(abi.encodePacked("ZKNOX_v0.14")); + address iVerifier_algo = address(falcon); + bytes memory pk=hex"09bc10a933624770811dc5e315526a3496c0e89b8e8436401a0848868c8b297ad7960a4f4df60bb2eba58b6d6828c99dce1d8b41ea6188af8e90081f3b2deee68a3888fb5ae87d99e2a110211cac1eadfa3a724c276a9108db19e8ff0add0da14aedd2073294ea7b682276edd449108e2b765ea2c03689b05fa6ba9146e16468325fdb39606472c61022f6679f247c16166c13af73994dc3dfa0b462b22747ee43a60f018eb5a26992805841c52b2b9ab829fbd4ed8b134625dbb95a10e62bbeeb806a95f985943472bc82ac510ae051ae2aff02a6cda68edfe971aef468356f075cb9b8c974566a3a46742123e78a79d96a941a94857e2acc3449955589ce80a6cc0ceb773224453b6309a280e659e585a68a98ea860869eba50a1d9776901babde4311638efc656cc564cc50987e1a8564e6e7bd47960d988f0a5a04746454528fab9cd89da9f1e534394229c91059f428b522cbf15eb359b9a08adfd3fe1d3548265a2e3b75c1f239df4e90734d704be8817b5639caa9d289fb4ee0f5e4d7603faff43d74734f8f6bdd9ff7b6578dac9e15949a54fa5465a925a61ebbb2f8eb858c1f487a9144840a1f9864f5ca49a7a63f6ec2a7f672c2c7ac18e973a1c0ca864e63db9f8731a996d1098809a89024f88bb8d757346993e52b138501315cf2086056060486870a5c437e886b8bcb422c0cde1ee081eddf18762a15926e8a8b5235b12d6d8ca5c60d72cfad3e755100d75096b5b8317ce7d5d36c5e01f7945a883cafa0a512e8edf28554c075145dec6798a3e2fac6cfa4851011b4906255521d5968102d10a92ff93d85b82d804469e90df8aee1b54212a66f461eb3514f29af958c326606e576254ef1a9ec83c62c568444d19e573b9c1c10d7a0b96fe4027a7a21c09b71cd7b271a828aa048203ae1691f5826e03a411e283dfa5a1a1b05bcf67ce6801590ab84a5d281edd573eadf50f6289d79b05b136ec16178d812d7f7e0f38cd9e83692064253f1dfda28ab97578dc0768fca404ef57ff24b463e3d50288970289e264a0eb9138a773fb114e0fd0c5fb5812186cea1f2a53ec133dfa3ad8809fd47cd56cb2e0185c266a17d263291753a47a2b531a5e9e4d29037646f934518c33e2c1fe2df5b2c0dea9fa2c751d689b24a819ce0f0bf82cab7b3adfc341a516b16c146a7c6a0e890a2d7451cf22459e3f3ab74b3076a62fbb11899a1a809357cb28a328761e0a4d56b501eca76a87169f560159c46a6a635b344c5"; + address iPQPublicKey = DeployPolynomial_NIST(salty, pk); + address ECDSAPublicKey=0x24D63ffC083dB45d713F970565AA322c71A6e79c; + module.initialize(iAlgoID, iVerifier_algo, ECDSAPublicKey, iPQPublicKey); + + vm.startBroadcast(address(kernelAlice)); + kernelAlice.installModule(MODULE_TYPE_VALIDATOR, address(module), + abi.encodePacked(HOOK_MODULE_NOT_INSTALLED, + abi.encode(data.validatorData, data.hookData, data.selectorData) + ) + ); + + // TODO: we don't need it if we don't have any custom function + InstallFallbackDataFormat memory fallbackData = InstallFallbackDataFormat(selectorData, hex""); + kernelAlice.installModule(MODULE_TYPE_FALLBACK, address(module), + abi.encodePacked( + selectorData, + HOOK_MODULE_NOT_INSTALLED, + abi.encode(abi.encodePacked(bytes1(0), bytes1(0), bytes1(0), bytes1(0)), fallbackData.hookData)) + ); + } + + function test_HelloWorld() external { + /*** HARD-CODED SIGNATURE ***/ + + bytes32 h = 0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750;//the hash signed by FALCON NIST and ECDSA, provided by etherjs for ECDSA and test_falcon.js for falcon + //the ecdsa signature + uint8 v = 28; + bytes32 r = 0xb53b48c0bd1639e836cc93b267aeff63bcc3d597211107d2e93ae71c2560a46e; + bytes32 s = 0x08c1f40ee7743dd09372566d171651195cbd963cf57b9ac7ea78b3879e71b8c8; + //the falcon signature + // forgefmt: disable-next-line + bytes memory sm=hex"0268530f8afbc74536b9a963b4f1c4cb738bcea7403d4d606b6e074ec5d3baf39d18726003ca37a62a7450b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750297ec2d4595cbb8c63969e43a166aa9bb8deec56e12b846277e35c5fed1c50c32e48b1196c107664e7e69485033f616a1e2f43472db23d5cc429ce91199ebcf7a4dec55238b1f6aca32e54bac3f1cc14fe8f53d48d5fe9f21f23be9c109c4254636c5d17778af36ffcb37a767b0a17febd893e674c2201e79fd574dd3cba94ea63767edeb3e6cea18f09dae8b0dabb440851ab7fdca10bf0138acec3275672324331dea466f69e86a4e6e6dec65a204275287e3b22d83ac8912feabd7c272f94d232120d27c0e625ca17d12c2c69b0eb26d2c94d81fbc7a5b0f30529bf502a73145508bb3bbb1f7c31db45f477ec9651f3bd7630daf8b170b1c1170a6cbf50b64c5ca559898c6ebfd46621d19fa13afd93579a654c5932bdebb9478a6943d838c4fb5e61a5ea65152191c8d0724d673d6fecff4bc29e90879a00cfe5e16b3713d6a43f5edad250d814670b20c1e629ab147a21e8c7604caec4adefe6cc14b1a2238942490489afdef48bfac1f6ee556f8a2edef9d83675748f58f9ed37467ac567a889dde8ea72ddf97a6f3fdf249c72ceb5f2f1915d2a08511079997b8a992ca18f651dea3a168f26cb8d011273784ecc9e381f676da0b0b77fb8fe09e5455a5499b6e5aed73619f3e3d9b7aafea679e1b36ab10c3e4b3f40082962c2a0f4b87786b691ff5246809b2ed94978afd76b357c9c7ef1256bbff0e82f279bad32aadc45bb339156288bf4202e110d81457a1b5299e272754999ec350fc57afffd9361e57024ca0dfa36d5da322795468c9532739ef5358e8902225b48ed6d964ffa7c46b18a8a9448b65704606b06b17e49ca2e46a13868978f3ed1d3c0943d8dc90b24de72714fc940"; + + /*** HARD-CODED SIGNATURE END ***/ + PackedUserOperation memory op = PackedUserOperation({ + sender: address(kernelAlice), + nonce: encodeNonce(), + initCode: abi.encodePacked(hex""), + callData : abi.encodePacked(ZKNOX_ZeroDev_Kernel_Module.helloWorld.selector), + accountGasLimits : bytes32(abi.encodePacked(uint128(10000000), uint128(10000000))), + preVerificationGas : 1000000, + gasFees : bytes32(abi.encodePacked(uint128(1), uint128(1))), + paymasterAndData : hex"", + signature : abi.encode(v, r, s, sm) + }); + PackedUserOperation[] memory ops = new PackedUserOperation[](1); + ops[0] = op; + entryPoint.handleOps{gas: 25000000}(ops, payable(address(1))); + } + + function encodeNonce() internal returns (uint256){ + ValidationMode mode = VALIDATION_MODE_DEFAULT; + uint192 nonceKey = ValidatorLib.encodeAsNonceKey( + ValidationMode.unwrap(mode), + ValidationType.unwrap(VALIDATION_TYPE_VALIDATOR), + bytes20(address(module)), + 0 // parallel key + ); + return entryPoint.getNonce(address(kernelAlice), nonceKey); + } +} diff --git a/solidity/test/ZKNOX_falconKATS.t.sol b/solidity/test/ZKNOX_falconKATS.t.sol index 31916c5..b615e34 100644 --- a/solidity/test/ZKNOX_falconKATS.t.sol +++ b/solidity/test/ZKNOX_falconKATS.t.sol @@ -147,15 +147,7 @@ function test_vector_prague() public{ (kpub, s2, salt, message) = decompress_KAT(pk, sm); - uint256[] memory hashed = hashToPointNIST(salt, message); - - //Display_HexArray(" hashToPoint", hashed); - - //Display_HexArray(" public key canonical form", kpub); - //Display_HexArray("sig canonical form", s2); - - //s2=Swap(s2); - //kpub=Swap(kpub); + uint256[] memory ntth = _ZKNOX_NTT_Compact(_ZKNOX_NTTFW_vectorized(kpub)); diff --git a/solidity/test/ZKNOX_hybrid.t.sol b/solidity/test/ZKNOX_hybrid.t.sol new file mode 100644 index 0000000..e9a1f9d --- /dev/null +++ b/solidity/test/ZKNOX_hybrid.t.sol @@ -0,0 +1,172 @@ + +pragma solidity ^0.8.25; + +import {Test, console} from "forge-std/Test.sol"; +import "../src/ZKNOX_falcon_encodings.sol"; +import "../src/ZKNOX_falcon.sol"; +import "../src/ZKNOX_falcon_deploy.sol"; +import "../src/ZKNOX_display.sol"; +import "../src/ZKNOX_hybrid.sol"; + +import "forge-std/Vm.sol"; + + +contract Hybrid_Test is Test { + ZKNOX_falcon falcon; + //exemple of stateless initialisation, no external contract provided + // Alice's address and private key (EOA with no initial contract code). + address payable ALICE_ADDRESS = payable(0x70997970C51812dc3A010C7d01b50e0d17dc79C8); + uint256 constant ALICE_PK = 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d; + + // Bob's address and private key (Bob will execute transactions on Alice's behalf). + address constant BOB_ADDRESS = 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC; + uint256 constant BOB_PK = 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a; + // Deployer's address and private key (used to deploy contracts). + address private constant DEPLOYER_ADDRESS = 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720; + uint256 private constant DEPLOYER_PK = 0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6; + + // The contract that Alice will delegate execution to. + + ZKNOX_HybridVerifier Verifier; + + + + //stateful initialisation + function setUp() public { + // Deploy the delegation contract (Alice will delegate calls to this contract). + + bytes memory pk=hex"09bc10a933624770811dc5e315526a3496c0e89b8e8436401a0848868c8b297ad7960a4f4df60bb2eba58b6d6828c99dce1d8b41ea6188af8e90081f3b2deee68a3888fb5ae87d99e2a110211cac1eadfa3a724c276a9108db19e8ff0add0da14aedd2073294ea7b682276edd449108e2b765ea2c03689b05fa6ba9146e16468325fdb39606472c61022f6679f247c16166c13af73994dc3dfa0b462b22747ee43a60f018eb5a26992805841c52b2b9ab829fbd4ed8b134625dbb95a10e62bbeeb806a95f985943472bc82ac510ae051ae2aff02a6cda68edfe971aef468356f075cb9b8c974566a3a46742123e78a79d96a941a94857e2acc3449955589ce80a6cc0ceb773224453b6309a280e659e585a68a98ea860869eba50a1d9776901babde4311638efc656cc564cc50987e1a8564e6e7bd47960d988f0a5a04746454528fab9cd89da9f1e534394229c91059f428b522cbf15eb359b9a08adfd3fe1d3548265a2e3b75c1f239df4e90734d704be8817b5639caa9d289fb4ee0f5e4d7603faff43d74734f8f6bdd9ff7b6578dac9e15949a54fa5465a925a61ebbb2f8eb858c1f487a9144840a1f9864f5ca49a7a63f6ec2a7f672c2c7ac18e973a1c0ca864e63db9f8731a996d1098809a89024f88bb8d757346993e52b138501315cf2086056060486870a5c437e886b8bcb422c0cde1ee081eddf18762a15926e8a8b5235b12d6d8ca5c60d72cfad3e755100d75096b5b8317ce7d5d36c5e01f7945a883cafa0a512e8edf28554c075145dec6798a3e2fac6cfa4851011b4906255521d5968102d10a92ff93d85b82d804469e90df8aee1b54212a66f461eb3514f29af958c326606e576254ef1a9ec83c62c568444d19e573b9c1c10d7a0b96fe4027a7a21c09b71cd7b271a828aa048203ae1691f5826e03a411e283dfa5a1a1b05bcf67ce6801590ab84a5d281edd573eadf50f6289d79b05b136ec16178d812d7f7e0f38cd9e83692064253f1dfda28ab97578dc0768fca404ef57ff24b463e3d50288970289e264a0eb9138a773fb114e0fd0c5fb5812186cea1f2a53ec133dfa3ad8809fd47cd56cb2e0185c266a17d263291753a47a2b531a5e9e4d29037646f934518c33e2c1fe2df5b2c0dea9fa2c751d689b24a819ce0f0bf82cab7b3adfc341a516b16c146a7c6a0e890a2d7451cf22459e3f3ab74b3076a62fbb11899a1a809357cb28a328761e0a4d56b501eca76a87169f560159c46a6a635b344c5"; + // forgefmt: disable-next-line + falcon = new ZKNOX_falcon(); + // public key in ntt form + // forgefmt: disable-next-line + + uint256 iAlgoID = FALCONSHAKE_ID; + + bytes32 salty = keccak256(abi.encodePacked("ZKNOX_v0.14")); + + address iVerifier_algo = address(falcon); + address iPQPublicKey = DeployPolynomial_NIST(salty, pk); + address ECDSAPublicKey=0x24D63ffC083dB45d713F970565AA322c71A6e79c; + + Verifier = new ZKNOX_HybridVerifier(); + + // Alice signs a delegation allowing `implementation` to execute transactions on her behalf. + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(Verifier), ALICE_PK); + + vm.attachDelegation(signedDelegation); + ZKNOX_HybridVerifier aliceVerifier = ZKNOX_HybridVerifier(ALICE_ADDRESS); + aliceVerifier.initialize(iAlgoID, iVerifier_algo, ECDSAPublicKey, iPQPublicKey); + console.log("param Verifier:", aliceVerifier.algoID(), aliceVerifier.CoreAddress(), aliceVerifier.authorized_PQPublicKey()); + + } + + //unitary test of joint ECDSA+falcon + function test_prague_hybridsig() public returns (address) { + bytes32 h = 0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750;//the hash signed by FALCON NIST and ECDSA, provided by etherjs for ECDSA and test_falcon.js for falcon + // forgefmt: disable-next-line + bytes memory pk=hex"09bc10a933624770811dc5e315526a3496c0e89b8e8436401a0848868c8b297ad7960a4f4df60bb2eba58b6d6828c99dce1d8b41ea6188af8e90081f3b2deee68a3888fb5ae87d99e2a110211cac1eadfa3a724c276a9108db19e8ff0add0da14aedd2073294ea7b682276edd449108e2b765ea2c03689b05fa6ba9146e16468325fdb39606472c61022f6679f247c16166c13af73994dc3dfa0b462b22747ee43a60f018eb5a26992805841c52b2b9ab829fbd4ed8b134625dbb95a10e62bbeeb806a95f985943472bc82ac510ae051ae2aff02a6cda68edfe971aef468356f075cb9b8c974566a3a46742123e78a79d96a941a94857e2acc3449955589ce80a6cc0ceb773224453b6309a280e659e585a68a98ea860869eba50a1d9776901babde4311638efc656cc564cc50987e1a8564e6e7bd47960d988f0a5a04746454528fab9cd89da9f1e534394229c91059f428b522cbf15eb359b9a08adfd3fe1d3548265a2e3b75c1f239df4e90734d704be8817b5639caa9d289fb4ee0f5e4d7603faff43d74734f8f6bdd9ff7b6578dac9e15949a54fa5465a925a61ebbb2f8eb858c1f487a9144840a1f9864f5ca49a7a63f6ec2a7f672c2c7ac18e973a1c0ca864e63db9f8731a996d1098809a89024f88bb8d757346993e52b138501315cf2086056060486870a5c437e886b8bcb422c0cde1ee081eddf18762a15926e8a8b5235b12d6d8ca5c60d72cfad3e755100d75096b5b8317ce7d5d36c5e01f7945a883cafa0a512e8edf28554c075145dec6798a3e2fac6cfa4851011b4906255521d5968102d10a92ff93d85b82d804469e90df8aee1b54212a66f461eb3514f29af958c326606e576254ef1a9ec83c62c568444d19e573b9c1c10d7a0b96fe4027a7a21c09b71cd7b271a828aa048203ae1691f5826e03a411e283dfa5a1a1b05bcf67ce6801590ab84a5d281edd573eadf50f6289d79b05b136ec16178d812d7f7e0f38cd9e83692064253f1dfda28ab97578dc0768fca404ef57ff24b463e3d50288970289e264a0eb9138a773fb114e0fd0c5fb5812186cea1f2a53ec133dfa3ad8809fd47cd56cb2e0185c266a17d263291753a47a2b531a5e9e4d29037646f934518c33e2c1fe2df5b2c0dea9fa2c751d689b24a819ce0f0bf82cab7b3adfc341a516b16c146a7c6a0e890a2d7451cf22459e3f3ab74b3076a62fbb11899a1a809357cb28a328761e0a4d56b501eca76a87169f560159c46a6a635b344c5"; + + // forgefmt: disable-next-line + bytes memory sm=hex"0268530f8afbc74536b9a963b4f1c4cb738bcea7403d4d606b6e074ec5d3baf39d18726003ca37a62a7450b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750297ec2d4595cbb8c63969e43a166aa9bb8deec56e12b846277e35c5fed1c50c32e48b1196c107664e7e69485033f616a1e2f43472db23d5cc429ce91199ebcf7a4dec55238b1f6aca32e54bac3f1cc14fe8f53d48d5fe9f21f23be9c109c4254636c5d17778af36ffcb37a767b0a17febd893e674c2201e79fd574dd3cba94ea63767edeb3e6cea18f09dae8b0dabb440851ab7fdca10bf0138acec3275672324331dea466f69e86a4e6e6dec65a204275287e3b22d83ac8912feabd7c272f94d232120d27c0e625ca17d12c2c69b0eb26d2c94d81fbc7a5b0f30529bf502a73145508bb3bbb1f7c31db45f477ec9651f3bd7630daf8b170b1c1170a6cbf50b64c5ca559898c6ebfd46621d19fa13afd93579a654c5932bdebb9478a6943d838c4fb5e61a5ea65152191c8d0724d673d6fecff4bc29e90879a00cfe5e16b3713d6a43f5edad250d814670b20c1e629ab147a21e8c7604caec4adefe6cc14b1a2238942490489afdef48bfac1f6ee556f8a2edef9d83675748f58f9ed37467ac567a889dde8ea72ddf97a6f3fdf249c72ceb5f2f1915d2a08511079997b8a992ca18f651dea3a168f26cb8d011273784ecc9e381f676da0b0b77fb8fe09e5455a5499b6e5aed73619f3e3d9b7aafea679e1b36ab10c3e4b3f40082962c2a0f4b87786b691ff5246809b2ed94978afd76b357c9c7ef1256bbff0e82f279bad32aadc45bb339156288bf4202e110d81457a1b5299e272754999ec350fc57afffd9361e57024ca0dfa36d5da322795468c9532739ef5358e8902225b48ed6d964ffa7c46b18a8a9448b65704606b06b17e49ca2e46a13868978f3ed1d3c0943d8dc90b24de72714fc940"; + //Public Key X: 0x25d78deee0f08530687ba1b624bcdbd4560e55d61334e406b7bfd59b9b889d27 + //Public Key Y: 0x075d427f734aa0e304938358e610fae302996ee2593deb9117a03d89baabcd95 + + //the ecdsa signature + uint8 v = 28; + bytes32 r = 0xb53b48c0bd1639e836cc93b267aeff63bcc3d597211107d2e93ae71c2560a46e; + bytes32 s = 0x08c1f40ee7743dd09372566d171651195cbd963cf57b9ac7ea78b3879e71b8c8; + + address res= ecrecover(h, v, r, s); + assertEq(uint160(0x24D63ffC083dB45d713F970565AA322c71A6e79c), uint160(res)); + + + uint256[] memory kpub; + uint256[] memory s2; + + uint256[] memory cs2; + bytes memory salt; + bytes memory message; + + (kpub, s2, salt, message) = decompress_KAT(pk, sm); + + uint256[] memory ntth = _ZKNOX_NTT_Compact(_ZKNOX_NTTFW_vectorized(kpub)); + + cs2 = _ZKNOX_NTT_Compact(s2); + + console.log("ntth length:", ntth.length); + console.log("ntthh[0]:"); + + for(uint i=0;i<1;i++){ + console.log("%x",ntth[i]); + } + + console.log("salt:"); + console.logBytes(salt); + + console.log("message:"); + console.logBytes(message); + + bool result = falcon.verify(message, salt, cs2, ntth); + + console.log("result", result); + + return res; + } + + + function testVector0_prague_hybridsig_delegation() public { + bytes32 h = 0x50b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750;//the hash signed by FALCON NIST and ECDSA, provided by etherjs for ECDSA and test_falcon.js for falcon + //the ecdsa signature + uint8 v = 28; + bytes32 r = 0xb53b48c0bd1639e836cc93b267aeff63bcc3d597211107d2e93ae71c2560a46e; + bytes32 s = 0x08c1f40ee7743dd09372566d171651195cbd963cf57b9ac7ea78b3879e71b8c8; + //the falcon signature + // forgefmt: disable-next-line + bytes memory sm=hex"0268530f8afbc74536b9a963b4f1c4cb738bcea7403d4d606b6e074ec5d3baf39d18726003ca37a62a7450b2c43fd39106bafbba0da34fc430e1f91e3c96ea2acee2bc34119f92b37750297ec2d4595cbb8c63969e43a166aa9bb8deec56e12b846277e35c5fed1c50c32e48b1196c107664e7e69485033f616a1e2f43472db23d5cc429ce91199ebcf7a4dec55238b1f6aca32e54bac3f1cc14fe8f53d48d5fe9f21f23be9c109c4254636c5d17778af36ffcb37a767b0a17febd893e674c2201e79fd574dd3cba94ea63767edeb3e6cea18f09dae8b0dabb440851ab7fdca10bf0138acec3275672324331dea466f69e86a4e6e6dec65a204275287e3b22d83ac8912feabd7c272f94d232120d27c0e625ca17d12c2c69b0eb26d2c94d81fbc7a5b0f30529bf502a73145508bb3bbb1f7c31db45f477ec9651f3bd7630daf8b170b1c1170a6cbf50b64c5ca559898c6ebfd46621d19fa13afd93579a654c5932bdebb9478a6943d838c4fb5e61a5ea65152191c8d0724d673d6fecff4bc29e90879a00cfe5e16b3713d6a43f5edad250d814670b20c1e629ab147a21e8c7604caec4adefe6cc14b1a2238942490489afdef48bfac1f6ee556f8a2edef9d83675748f58f9ed37467ac567a889dde8ea72ddf97a6f3fdf249c72ceb5f2f1915d2a08511079997b8a992ca18f651dea3a168f26cb8d011273784ecc9e381f676da0b0b77fb8fe09e5455a5499b6e5aed73619f3e3d9b7aafea679e1b36ab10c3e4b3f40082962c2a0f4b87786b691ff5246809b2ed94978afd76b357c9c7ef1256bbff0e82f279bad32aadc45bb339156288bf4202e110d81457a1b5299e272754999ec350fc57afffd9361e57024ca0dfa36d5da322795468c9532739ef5358e8902225b48ed6d964ffa7c46b18a8a9448b65704606b06b17e49ca2e46a13868978f3ed1d3c0943d8dc90b24de72714fc940"; + + + vm.startBroadcast(ALICE_PK); + + // Debug: Print stored values to verify correct setup + + + + console.log( + "Stored authorizedPublicKey at Alice (ecdsa):", + address(uint160(uint256(vm.load(ALICE_ADDRESS, bytes32(uint256(0)))))) + ); + console.log( + "Stored authorizedPQPublicKey at Alice (falcon):", + address(uint160(uint256(vm.load(ALICE_ADDRESS, bytes32(uint256(0)))))) + ); + console.log( + "Stored CoreAddress at Alice:", address(uint160(uint256(vm.load(ALICE_ADDRESS, bytes32(uint256(1)))))) + ); + console.log("Stored algoID at Alice:", uint256(vm.load(ALICE_ADDRESS, bytes32(uint256(2))))); + console.log("Stored nonce at Alice:", uint256(vm.load(ALICE_ADDRESS, bytes32(uint256(3))))); + + // As Bob, execute the transaction via Alice's temporarily assigned contract. + vm.stopBroadcast(); + + vm.broadcast(BOB_PK); + bytes memory code = address(ALICE_ADDRESS).code; //this shall be ef0100, followed by adress + + console.log("Verifier address:%x", uint256(uint160(address(Verifier)))); + + console.log("code written at eoa Alice:"); + console.logBytes(code); + + // Verify that Alice's account now temporarily behaves as a smart contract. + require(code.length > 0, "no code written to Alice"); + + + + // As Bob, execute the transaction via Alice's temporarily assigned contract. + bool isValid=ZKNOX_HybridVerifier(ALICE_ADDRESS).isValid(h,v,r,s,sm); + console.log("signature result:", isValid); + + } + + +} \ No newline at end of file