Skip to content

Commit

Permalink
Merge pull request #680 from zama-ai/DecryptionOracle
Browse files Browse the repository at this point in the history
feat: new DecryptionOracle contract
  • Loading branch information
jatZama authored Dec 27, 2024
2 parents 2518cab + 87c9c4b commit edb5d3d
Show file tree
Hide file tree
Showing 21 changed files with 1,956 additions and 2,496 deletions.
4 changes: 2 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export MNEMONIC="adapt mosquito move limb mobile illegal tree voyage juice mosquito burger raise father hope layer"
export PRIVATE_KEY_FHEVM_DEPLOYER="0c66d8cde71d2faa29d0cb6e3a567d31279b6eace67b0a9d9ba869c119843a5e"
export PRIVATE_KEY_GATEWAY_DEPLOYER="717fd99986df414889fd8b51069d4f90a50af72e542c58ee065f5883779099c6"
export PRIVATE_KEY_GATEWAY_RELAYER="7ec931411ad75a7c201469a385d6f18a325d4923f9f213bd882bbea87e160b67"
export PRIVATE_KEY_DECRYPTION_ORACLE_DEPLOYER="717fd99986df414889fd8b51069d4f90a50af72e542c58ee065f5883779099c6"
export PRIVATE_KEY_DECRYPTION_ORACLE_RELAYER="7ec931411ad75a7c201469a385d6f18a325d4923f9f213bd882bbea87e160b67"
export NUM_KMS_SIGNERS="1"
export PRIVATE_KEY_KMS_SIGNER_0="388b7680e4e1afa06efbfd45cdd1fe39f3c6af381df6555a19661f283b97de91"
export PRIVATE_KEY_KMS_SIGNER_1="bbaed91514fa4b7c86aa4f73becbabcf4bce0ae130240f0d6ac3f87e06812440"
Expand Down
2 changes: 1 addition & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
*
!lib/**
!gateway/**
!decryption/**
!config/**
!package.json
!README.md
Expand Down
259 changes: 259 additions & 0 deletions decryption/DecryptionOracleCaller.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear

pragma solidity ^0.8.24;

import "../lib/TFHE.sol";
import "../lib/Impl.sol";

interface IKMSVerifier {
function verifyDecryptionEIP712KMSSignatures(
address aclAddress,
uint256[] memory handlesList,
bytes memory decryptedResult,
bytes[] memory signatures
) external returns (bool);
}

interface IDecryptionOracle {
function requestDecryption(uint256[] calldata ctsHandles, bytes4 callbackSelector) external returns (uint256);
}

struct DecryptionOracleConfigStruct {
address DecryptionOracleAddress;
}

abstract contract DecryptionOracleCaller {
error HandlesAlreadySavedForRequestID();
error NoHandleFoundForRequestID();
error InvalidKMSSignatures();
error UnsupportedHandleType();

mapping(uint256 => ebool[]) private paramsEBool;
mapping(uint256 => euint4[]) private paramsEUint4;
mapping(uint256 => euint8[]) private paramsEUint8;
mapping(uint256 => euint16[]) private paramsEUint16;
mapping(uint256 => euint32[]) private paramsEUint32;
mapping(uint256 => euint64[]) private paramsEUint64;
mapping(uint256 => eaddress[]) private paramsEAddress;
mapping(uint256 => address[]) private paramsAddress;
mapping(uint256 => uint256[]) private paramsUint256;
mapping(uint256 => uint256[]) private requestedHandles;

constructor() {}

function addParamsEBool(uint256 requestID, ebool _ebool) internal {
paramsEBool[requestID].push(_ebool);
}

function addParamsEUint4(uint256 requestID, euint4 _euint4) internal {
paramsEUint4[requestID].push(_euint4);
}

function addParamsEUint8(uint256 requestID, euint8 _euint8) internal {
paramsEUint8[requestID].push(_euint8);
}

function addParamsEUint16(uint256 requestID, euint16 _euint16) internal {
paramsEUint16[requestID].push(_euint16);
}

function addParamsEUint32(uint256 requestID, euint32 _euint32) internal {
paramsEUint32[requestID].push(_euint32);
}

function addParamsEUint64(uint256 requestID, euint64 _euint64) internal {
paramsEUint64[requestID].push(_euint64);
}

function addParamsEAddress(uint256 requestID, eaddress _eaddress) internal {
paramsEAddress[requestID].push(_eaddress);
}

function addParamsAddress(uint256 requestID, address _address) internal {
paramsAddress[requestID].push(_address);
}

function addParamsUint256(uint256 requestID, uint256 _uint) internal {
paramsUint256[requestID].push(_uint);
}

function saveRequestedHandles(uint256 requestID, uint256[] memory handlesList) internal {
if (requestedHandles[requestID].length != 0) {
revert HandlesAlreadySavedForRequestID();
}
requestedHandles[requestID] = handlesList;
}

function loadRequestedHandles(uint256 requestID) internal view returns (uint256[] memory) {
if (requestedHandles[requestID].length == 0) {
revert NoHandleFoundForRequestID();
}
return requestedHandles[requestID];
}

function getParamsEBool(uint256 requestID) internal view returns (ebool[] memory) {
return paramsEBool[requestID];
}

function getParamsEUint4(uint256 requestID) internal view returns (euint4[] memory) {
return paramsEUint4[requestID];
}

function getParamsEUint8(uint256 requestID) internal view returns (euint8[] memory) {
return paramsEUint8[requestID];
}

function getParamsEUint16(uint256 requestID) internal view returns (euint16[] memory) {
return paramsEUint16[requestID];
}

function getParamsEUint32(uint256 requestID) internal view returns (euint32[] memory) {
return paramsEUint32[requestID];
}

function getParamsEUint64(uint256 requestID) internal view returns (euint64[] memory) {
return paramsEUint64[requestID];
}

function getParamsEAddress(uint256 requestID) internal view returns (eaddress[] memory) {
return paramsEAddress[requestID];
}

function getParamsAddress(uint256 requestID) internal view returns (address[] memory) {
return paramsAddress[requestID];
}

function getParamsUint256(uint256 requestID) internal view returns (uint256[] memory) {
return paramsUint256[requestID];
}

// keccak256(abi.encode(uint256(keccak256("fhevm.storage.DecryptionOracleConfig")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant DecryptionOracleLocation =
0xde725b831312c6c6cbab76ff954da6836e26d78fc467781757c36be9c3d67d00;

function getDecryptionOracleConfig() internal pure returns (DecryptionOracleConfigStruct storage $) {
assembly {
$.slot := DecryptionOracleLocation
}
}

function setDecryptionOracle(address decryptionOracleAddress) internal {
DecryptionOracleConfigStruct storage $ = getDecryptionOracleConfig();
$.DecryptionOracleAddress = decryptionOracleAddress;
}

function gatewayContractAddress() internal view returns (address) {
DecryptionOracleConfigStruct storage $ = getDecryptionOracleConfig();
return $.DecryptionOracleAddress;
}

function toUint256(ebool newCT) internal pure returns (uint256 ct) {
ct = ebool.unwrap(newCT);
}

function toUint256(euint4 newCT) internal pure returns (uint256 ct) {
ct = euint4.unwrap(newCT);
}

function toUint256(euint8 newCT) internal pure returns (uint256 ct) {
ct = euint8.unwrap(newCT);
}

function toUint256(euint16 newCT) internal pure returns (uint256 ct) {
ct = euint16.unwrap(newCT);
}

function toUint256(euint32 newCT) internal pure returns (uint256 ct) {
ct = euint32.unwrap(newCT);
}

function toUint256(euint64 newCT) internal pure returns (uint256 ct) {
ct = euint64.unwrap(newCT);
}

function toUint256(euint128 newCT) internal pure returns (uint256 ct) {
ct = euint128.unwrap(newCT);
}

function toUint256(eaddress newCT) internal pure returns (uint256 ct) {
ct = eaddress.unwrap(newCT);
}

function toUint256(euint256 newCT) internal pure returns (uint256 ct) {
ct = euint256.unwrap(newCT);
}

function toUint256(ebytes64 newCT) internal pure returns (uint256 ct) {
ct = ebytes64.unwrap(newCT);
}

function toUint256(ebytes128 newCT) internal pure returns (uint256 ct) {
ct = ebytes128.unwrap(newCT);
}

function toUint256(ebytes256 newCT) internal pure returns (uint256 ct) {
ct = ebytes256.unwrap(newCT);
}

function requestDecryption(
uint256[] memory ctsHandles,
bytes4 callbackSelector
) internal returns (uint256 requestID) {
FHEVMConfigStruct storage $ = Impl.getFHEVMConfig();
IACL($.ACLAddress).allowForDecryption(ctsHandles);
DecryptionOracleConfigStruct storage $$ = getDecryptionOracleConfig();
requestID = IDecryptionOracle($$.DecryptionOracleAddress).requestDecryption(ctsHandles, callbackSelector);
saveRequestedHandles(requestID, ctsHandles);
}

/// @dev this function should be called inside the callback function the dApp contract to verify the signatures
function verifySignatures(uint256[] memory handlesList, bytes[] memory signatures) internal returns (bool) {
uint256 start = 4 + 32; // start position after skipping the selector (4 bytes) and the first argument (index, 32 bytes)
uint256 length = getSignedDataLength(handlesList);
bytes memory decryptedResult = new bytes(length);
assembly {
calldatacopy(add(decryptedResult, 0x20), start, length) // Copy the relevant part of calldata to decryptedResult memory
}
FHEVMConfigStruct storage $ = Impl.getFHEVMConfig();
return
IKMSVerifier($.KMSVerifierAddress).verifyDecryptionEIP712KMSSignatures(
$.ACLAddress,
handlesList,
decryptedResult,
signatures
);
}

function getSignedDataLength(uint256[] memory handlesList) private pure returns (uint256) {
uint256 handlesListlen = handlesList.length;
uint256 signedDataLength;
for (uint256 i = 0; i < handlesListlen; i++) {
uint8 typeCt = uint8(handlesList[i] >> 8);
if (typeCt < 9) {
signedDataLength += 32;
} else if (typeCt == 9) {
//ebytes64
signedDataLength += 128;
} else if (typeCt == 10) {
//ebytes128
signedDataLength += 192;
} else if (typeCt == 11) {
//ebytes256
signedDataLength += 320;
} else {
revert UnsupportedHandleType();
}
}
signedDataLength += 32; // add offset of signatures
return signedDataLength;
}

modifier checkSignatures(uint256 requestID, bytes[] memory signatures) {
uint256[] memory handlesList = loadRequestedHandles(requestID);
bool isVerified = verifySignatures(handlesList, signatures);
if (!isVerified) {
revert InvalidKMSSignatures();
}
_;
}
}
Loading

0 comments on commit edb5d3d

Please sign in to comment.