mirror of
https://github.com/zama-ai/fhevm-solidity.git
synced 2026-01-13 14:38:01 -05:00
528 lines
21 KiB
Solidity
528 lines
21 KiB
Solidity
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
|
|
pragma solidity ^0.8.24;
|
|
|
|
import "../lib/TFHE.sol";
|
|
import "./FHEVMConfig.sol";
|
|
import "../decryption/DecryptionOracleCaller.sol";
|
|
import "./DecryptionOracleConfig.sol";
|
|
|
|
/// @notice Contract for testing asynchronous decryption using the Gateway
|
|
contract TestAsyncDecrypt is DecryptionOracleCaller {
|
|
/// @dev Encrypted state variables
|
|
ebool xBool;
|
|
euint4 xUint4;
|
|
euint8 xUint8;
|
|
euint16 xUint16;
|
|
euint32 xUint32;
|
|
euint64 xUint64;
|
|
euint64 xUint64_2;
|
|
euint64 xUint64_3;
|
|
euint128 xUint128;
|
|
eaddress xAddress;
|
|
eaddress xAddress2;
|
|
euint256 xUint256;
|
|
|
|
/// @dev Decrypted state variables
|
|
bool public yBool;
|
|
uint8 public yUint4;
|
|
uint8 public yUint8;
|
|
uint16 public yUint16;
|
|
uint32 public yUint32;
|
|
uint64 public yUint64;
|
|
uint64 public yUint64_2;
|
|
uint64 public yUint64_3;
|
|
uint128 public yUint128;
|
|
address public yAddress;
|
|
address public yAddress2;
|
|
uint256 public yUint256;
|
|
bytes public yBytes64;
|
|
bytes public yBytes128;
|
|
bytes public yBytes256;
|
|
|
|
/// @dev Tracks the latest decryption request ID
|
|
uint256 public latestRequestID;
|
|
|
|
/// @notice Constructor to initialize the contract and set up encrypted values
|
|
constructor() {
|
|
TFHE.setFHEVM(FHEVMConfig.defaultConfig());
|
|
setDecryptionOracle(DECRYPTION_ORACLE_ADDRESS);
|
|
|
|
/// @dev Initialize encrypted variables with sample values
|
|
xBool = TFHE.asEbool(true);
|
|
TFHE.allowThis(xBool);
|
|
xUint4 = TFHE.asEuint4(4);
|
|
TFHE.allowThis(xUint4);
|
|
xUint8 = TFHE.asEuint8(42);
|
|
TFHE.allowThis(xUint8);
|
|
xUint16 = TFHE.asEuint16(16);
|
|
TFHE.allowThis(xUint16);
|
|
xUint32 = TFHE.asEuint32(32);
|
|
TFHE.allowThis(xUint32);
|
|
xUint64 = TFHE.asEuint64(18446744073709551600);
|
|
TFHE.allowThis(xUint64);
|
|
xUint64_2 = TFHE.asEuint64(76575465786);
|
|
TFHE.allowThis(xUint64_2);
|
|
xUint64_3 = TFHE.asEuint64(6400);
|
|
TFHE.allowThis(xUint64_3);
|
|
xUint128 = TFHE.asEuint128(1267650600228229401496703205443);
|
|
TFHE.allowThis(xUint128);
|
|
xUint256 = TFHE.asEuint256(27606985387162255149739023449108101809804435888681546220650096895197251);
|
|
TFHE.allowThis(xUint256);
|
|
xAddress = TFHE.asEaddress(0x8ba1f109551bD432803012645Ac136ddd64DBA72);
|
|
TFHE.allowThis(xAddress);
|
|
xAddress2 = TFHE.asEaddress(0xf48b8840387ba3809DAE990c930F3b4766A86ca3);
|
|
TFHE.allowThis(xAddress2);
|
|
}
|
|
|
|
/// @notice Function to request decryption of a boolean value with an infinite loop in the callback
|
|
function requestBoolInfinite() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(xBool);
|
|
requestDecryption(cts, this.callbackBoolInfinite.selector);
|
|
}
|
|
|
|
/// @notice Callback function for the infinite loop decryption request (WARNING: This function will never complete)
|
|
function callbackBoolInfinite(
|
|
uint256 requestID,
|
|
bool decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (bool) {
|
|
uint256 i = 0;
|
|
while (true) {
|
|
i++;
|
|
}
|
|
yBool = decryptedInput;
|
|
return yBool;
|
|
}
|
|
|
|
/// @notice Request decryption of a boolean value
|
|
function requestBool() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(xBool);
|
|
requestDecryption(cts, this.callbackBool.selector);
|
|
}
|
|
|
|
/// @notice Attempt to request decryption of a fake boolean value (should revert)
|
|
function requestFakeBool() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = uint256(0x4200000000000000000000000000000000000000000000000000000000000000);
|
|
/// @dev This should revert because the previous ebool is not honestly obtained
|
|
requestDecryption(cts, this.callbackBool.selector);
|
|
}
|
|
|
|
/// @notice Callback function for boolean decryption
|
|
function callbackBool(
|
|
uint256 requestID,
|
|
bool decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (bool) {
|
|
yBool = decryptedInput;
|
|
return yBool;
|
|
}
|
|
|
|
/// @notice Request decryption of a 4-bit unsigned integer
|
|
function requestUint4() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(xUint4);
|
|
requestDecryption(cts, this.callbackUint4.selector);
|
|
}
|
|
|
|
/// @notice Attempt to request decryption of a fake 4-bit unsigned integer (should revert)
|
|
function requestFakeUint4() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = uint256(0x4200000000000000000000000000000000000000000000000000000000000100);
|
|
/// @dev This should revert because the previous handle is not honestly obtained
|
|
requestDecryption(cts, this.callbackUint4.selector);
|
|
}
|
|
|
|
/// @notice Callback function for 4-bit unsigned integer decryption
|
|
/// @param decryptedInput The decrypted 4-bit unsigned integer
|
|
/// @return The decrypted value
|
|
function callbackUint4(
|
|
uint256 requestID,
|
|
uint8 decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (uint8) {
|
|
yUint4 = decryptedInput;
|
|
return decryptedInput;
|
|
}
|
|
|
|
/// @notice Request decryption of an 8-bit unsigned integer
|
|
function requestUint8() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(xUint8);
|
|
requestDecryption(cts, this.callbackUint8.selector);
|
|
}
|
|
|
|
/// @notice Attempt to request decryption of a fake 8-bit unsigned integer (should revert)
|
|
function requestFakeUint8() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = uint256(0x4200000000000000000000000000000000000000000000000000000000000200);
|
|
/// @dev This should revert because the previous handle is not honestly obtained
|
|
requestDecryption(cts, this.callbackUint8.selector);
|
|
}
|
|
|
|
/// @notice Callback function for 8-bit unsigned integer decryption
|
|
/// @param decryptedInput The decrypted 8-bit unsigned integer
|
|
/// @return The decrypted value
|
|
function callbackUint8(
|
|
uint256 requestID,
|
|
uint8 decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (uint8) {
|
|
yUint8 = decryptedInput;
|
|
return decryptedInput;
|
|
}
|
|
|
|
/// @notice Request decryption of a 16-bit unsigned integer
|
|
function requestUint16() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(xUint16);
|
|
requestDecryption(cts, this.callbackUint16.selector);
|
|
}
|
|
|
|
/// @notice Attempt to request decryption of a fake 16-bit unsigned integer (should revert)
|
|
function requestFakeUint16() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = uint256(0x4200000000000000000000000000000000000000000000000000000000000300);
|
|
/// @dev This should revert because the previous handle is not honestly obtained
|
|
requestDecryption(cts, this.callbackUint16.selector);
|
|
}
|
|
|
|
/// @notice Callback function for 16-bit unsigned integer decryption
|
|
/// @param decryptedInput The decrypted 16-bit unsigned integer
|
|
/// @return The decrypted value
|
|
function callbackUint16(
|
|
uint256 requestID,
|
|
uint16 decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (uint16) {
|
|
yUint16 = decryptedInput;
|
|
return decryptedInput;
|
|
}
|
|
|
|
/// @notice Request decryption of a 32-bit unsigned integer with additional inputs
|
|
/// @param input1 First additional input
|
|
/// @param input2 Second additional input
|
|
function requestUint32(uint32 input1, uint32 input2) public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(xUint32);
|
|
uint256 requestID = requestDecryption(cts, this.callbackUint32.selector);
|
|
addParamsUint256(requestID, input1);
|
|
addParamsUint256(requestID, input2);
|
|
}
|
|
|
|
/// @notice Attempt to request decryption of a fake 32-bit unsigned integer (should revert)
|
|
function requestFakeUint32() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = uint256(0x4200000000000000000000000000000000000000000000000000000000000400);
|
|
/// @dev This should revert because the previous handle is not honestly obtained
|
|
requestDecryption(cts, this.callbackUint32.selector);
|
|
}
|
|
|
|
/// @notice Callback function for 32-bit unsigned integer decryption
|
|
/// @param requestID The ID of the decryption request
|
|
/// @param decryptedInput The decrypted 32-bit unsigned integer
|
|
/// @return The result of the computation
|
|
function callbackUint32(
|
|
uint256 requestID,
|
|
uint32 decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (uint32) {
|
|
uint256[] memory params = getParamsUint256(requestID);
|
|
unchecked {
|
|
uint32 result = uint32(params[0]) + uint32(params[1]) + decryptedInput;
|
|
yUint32 = result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// @notice Request decryption of a 64-bit unsigned integer
|
|
function requestUint64() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(xUint64);
|
|
requestDecryption(cts, this.callbackUint64.selector);
|
|
}
|
|
|
|
/// @notice Attempt to request decryption of a fake 64-bit unsigned integer (should revert)
|
|
function requestFakeUint64() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = uint256(0x4200000000000000000000000000000000000000000000000000000000000500);
|
|
/// @dev This should revert because the previous handle is not honestly obtained
|
|
requestDecryption(cts, this.callbackUint64.selector);
|
|
}
|
|
|
|
/// @notice Request decryption of a non-trivial 64-bit unsigned integer
|
|
/// @param inputHandle The input handle for the encrypted value
|
|
/// @param inputProof The input proof for the encrypted value
|
|
function requestUint64NonTrivial(einput inputHandle, bytes calldata inputProof) public {
|
|
euint64 inputNonTrivial = TFHE.asEuint64(inputHandle, inputProof);
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(inputNonTrivial);
|
|
requestDecryption(cts, this.callbackUint64.selector);
|
|
}
|
|
|
|
/// @notice Callback function for 64-bit unsigned integer decryption
|
|
/// @param decryptedInput The decrypted 64-bit unsigned integer
|
|
/// @return The decrypted value
|
|
function callbackUint64(
|
|
uint256 requestID,
|
|
uint64 decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (uint64) {
|
|
yUint64 = decryptedInput;
|
|
return decryptedInput;
|
|
}
|
|
|
|
function requestUint128() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(xUint128);
|
|
requestDecryption(cts, this.callbackUint128.selector);
|
|
}
|
|
|
|
function requestUint128NonTrivial(einput inputHandle, bytes calldata inputProof) public {
|
|
euint128 inputNonTrivial = TFHE.asEuint128(inputHandle, inputProof);
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(inputNonTrivial);
|
|
requestDecryption(cts, this.callbackUint128.selector);
|
|
}
|
|
|
|
function callbackUint128(
|
|
uint256 requestID,
|
|
uint128 decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (uint128) {
|
|
yUint128 = decryptedInput;
|
|
return decryptedInput;
|
|
}
|
|
|
|
function requestUint256() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(xUint256);
|
|
requestDecryption(cts, this.callbackUint256.selector);
|
|
}
|
|
|
|
function requestUint256NonTrivial(einput inputHandle, bytes calldata inputProof) public {
|
|
euint256 inputNonTrivial = TFHE.asEuint256(inputHandle, inputProof);
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(inputNonTrivial);
|
|
requestDecryption(cts, this.callbackUint256.selector);
|
|
}
|
|
|
|
function callbackUint256(
|
|
uint256 requestID,
|
|
uint256 decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (uint256) {
|
|
yUint256 = decryptedInput;
|
|
return decryptedInput;
|
|
}
|
|
|
|
function requestEbytes64NonTrivial(einput inputHandle, bytes calldata inputProof) public {
|
|
ebytes64 inputNonTrivial = TFHE.asEbytes64(inputHandle, inputProof);
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(inputNonTrivial);
|
|
requestDecryption(cts, this.callbackBytes64.selector);
|
|
}
|
|
|
|
function requestEbytes64Trivial(bytes calldata value) public {
|
|
ebytes64 inputTrivial = TFHE.asEbytes64(TFHE.padToBytes64(value));
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(inputTrivial);
|
|
requestDecryption(cts, this.callbackBytes64.selector);
|
|
}
|
|
|
|
function callbackBytes64(
|
|
uint256 requestID,
|
|
bytes calldata decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (bytes memory) {
|
|
yBytes64 = decryptedInput;
|
|
return decryptedInput;
|
|
}
|
|
|
|
function requestEbytes128NonTrivial(einput inputHandle, bytes calldata inputProof) public {
|
|
ebytes128 inputNonTrivial = TFHE.asEbytes128(inputHandle, inputProof);
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(inputNonTrivial);
|
|
requestDecryption(cts, this.callbackBytes128.selector);
|
|
}
|
|
|
|
function requestEbytes128Trivial(bytes calldata value) public {
|
|
ebytes128 inputTrivial = TFHE.asEbytes128(TFHE.padToBytes128(value));
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(inputTrivial);
|
|
requestDecryption(cts, this.callbackBytes128.selector);
|
|
}
|
|
|
|
function callbackBytes128(
|
|
uint256 requestID,
|
|
bytes calldata decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (bytes memory) {
|
|
yBytes128 = decryptedInput;
|
|
return decryptedInput;
|
|
}
|
|
|
|
function requestEbytes256Trivial(bytes calldata value) public {
|
|
ebytes256 inputTrivial = TFHE.asEbytes256(TFHE.padToBytes256(value));
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(inputTrivial);
|
|
requestDecryption(cts, this.callbackBytes256.selector);
|
|
}
|
|
|
|
function requestEbytes256NonTrivial(einput inputHandle, bytes calldata inputProof) public {
|
|
ebytes256 inputNonTrivial = TFHE.asEbytes256(inputHandle, inputProof);
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(inputNonTrivial);
|
|
requestDecryption(cts, this.callbackBytes256.selector);
|
|
}
|
|
|
|
/// @notice Callback function for 256-bit encrypted bytes decryption
|
|
/// @param decryptedInput The decrypted 256-bit bytes
|
|
/// @return The decrypted value
|
|
function callbackBytes256(
|
|
uint256 requestID,
|
|
bytes calldata decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (bytes memory) {
|
|
yBytes256 = decryptedInput;
|
|
return decryptedInput;
|
|
}
|
|
|
|
/// @notice Request decryption of an encrypted address
|
|
function requestAddress() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = toUint256(xAddress);
|
|
requestDecryption(cts, this.callbackAddress.selector);
|
|
}
|
|
|
|
/// @notice Request decryption of multiple encrypted addresses
|
|
function requestSeveralAddresses() public {
|
|
uint256[] memory cts = new uint256[](2);
|
|
cts[0] = toUint256(xAddress);
|
|
cts[1] = toUint256(xAddress2);
|
|
requestDecryption(cts, this.callbackAddresses.selector);
|
|
}
|
|
|
|
/// @notice Callback function for multiple address decryption
|
|
/// @param decryptedInput1 The first decrypted address
|
|
/// @param decryptedInput2 The second decrypted address
|
|
/// @return The first decrypted address
|
|
function callbackAddresses(
|
|
uint256 requestID,
|
|
address decryptedInput1,
|
|
address decryptedInput2,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (address) {
|
|
yAddress = decryptedInput1;
|
|
yAddress2 = decryptedInput2;
|
|
return decryptedInput1;
|
|
}
|
|
|
|
/// @notice Attempt to request decryption of a fake address (should revert)
|
|
function requestFakeAddress() public {
|
|
uint256[] memory cts = new uint256[](1);
|
|
cts[0] = uint256(0x4200000000000000000000000000000000000000000000000000000000000700);
|
|
/// @dev This should revert because the previous handle is not honestly obtained
|
|
requestDecryption(cts, this.callbackAddress.selector);
|
|
}
|
|
|
|
/// @notice Callback function for address decryption
|
|
/// @param decryptedInput The decrypted address
|
|
/// @return The decrypted address
|
|
function callbackAddress(
|
|
uint256 requestID,
|
|
address decryptedInput,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (address) {
|
|
yAddress = decryptedInput;
|
|
return decryptedInput;
|
|
}
|
|
|
|
/// @notice Request decryption of multiple encrypted data types
|
|
/// @dev This function demonstrates how to request decryption for various encrypted data types in a single call
|
|
/// @param input1 First additional input parameter for the callback function
|
|
/// @param input2 Second additional input parameter for the callback function
|
|
function requestMixed(uint32 input1, uint32 input2) public {
|
|
uint256[] memory cts = new uint256[](6);
|
|
cts[0] = toUint256(xBool);
|
|
cts[1] = toUint256(xUint4);
|
|
cts[2] = toUint256(xUint8);
|
|
cts[3] = toUint256(xUint16);
|
|
cts[4] = toUint256(xUint32);
|
|
cts[5] = toUint256(xAddress);
|
|
uint256 requestID = requestDecryption(cts, this.callbackMixed.selector);
|
|
addParamsUint256(requestID, input1);
|
|
addParamsUint256(requestID, input2);
|
|
}
|
|
|
|
/// @notice Callback function for mixed data type decryption
|
|
/// @dev Processes the decrypted values and performs some basic checks
|
|
/// @param requestID The ID of the decryption request
|
|
/// @param decBool First decrypted boolean
|
|
/// @param decUint4 Decrypted 4-bit unsigned integer
|
|
/// @param decUint8 Decrypted 8-bit unsigned integer
|
|
/// @param decUint16 Decrypted 16-bit unsigned integer
|
|
/// @param decUint32 Decrypted 32-bit unsigned integer
|
|
/// @param decAddress Decrypted address
|
|
/// @return The decrypted 4-bit unsigned integer
|
|
function callbackMixed(
|
|
uint256 requestID,
|
|
bool decBool,
|
|
uint8 decUint4,
|
|
uint8 decUint8,
|
|
uint16 decUint16,
|
|
uint32 decUint32,
|
|
address decAddress,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) returns (uint8) {
|
|
yBool = decBool;
|
|
yUint4 = decUint4;
|
|
yUint8 = decUint8;
|
|
yUint16 = decUint16;
|
|
uint256[] memory params = getParamsUint256(requestID);
|
|
unchecked {
|
|
uint32 result = uint32(params[0]) + uint32(params[1]) + decUint32;
|
|
yUint32 = result;
|
|
}
|
|
yAddress = decAddress;
|
|
return yUint4;
|
|
}
|
|
|
|
/// @notice Request decryption of mixed data types including 256-bit encrypted bytes
|
|
/// @dev Demonstrates how to include encrypted bytes256 in a mixed decryption request
|
|
/// @param inputHandle The encrypted input handle for the bytes256
|
|
/// @param inputProof The proof for the encrypted bytes256
|
|
function requestMixedBytes256(einput inputHandle, bytes calldata inputProof) public {
|
|
ebytes256 xBytes256 = TFHE.asEbytes256(inputHandle, inputProof);
|
|
uint256[] memory cts = new uint256[](4);
|
|
cts[0] = toUint256(xBool);
|
|
cts[1] = toUint256(xAddress);
|
|
cts[2] = toUint256(xBytes256);
|
|
ebytes64 input64Bytes = TFHE.asEbytes64(TFHE.padToBytes64(hex"aaff42"));
|
|
cts[3] = toUint256(input64Bytes);
|
|
requestDecryption(cts, this.callbackMixedBytes256.selector);
|
|
}
|
|
|
|
/// @notice Callback function for mixed data type decryption including 256-bit encrypted bytes
|
|
/// @dev Processes and stores the decrypted values
|
|
/// @param decBool Decrypted boolean
|
|
/// @param decAddress Decrypted address
|
|
/// @param bytesRes Decrypted 256-bit bytes
|
|
function callbackMixedBytes256(
|
|
uint256 requestID,
|
|
bool decBool,
|
|
address decAddress,
|
|
bytes memory bytesRes,
|
|
bytes memory bytesRes2,
|
|
bytes[] memory signatures
|
|
) public checkSignatures(requestID, signatures) {
|
|
yBool = decBool;
|
|
yAddress = decAddress;
|
|
yBytes256 = bytesRes;
|
|
yBytes64 = bytesRes2;
|
|
}
|
|
}
|