The global decryption operation is asynchronous, and to enable decryption, the application contract must extend the GatewayCaller contract, which will automatically import the GatewayCaller solidity library.
Explanation of Steps: After generating a random number using randEuint8(), the contract must be permitted to access the unique ciphertext handle by calling TFHE.allow(). Next, prepare the list of ciphertext handles to be decrypted—in this example, a single random number. Calling requestDecryption will emit an EventDecryption event on the GatewayContract, which will then be picked up by the relayer.
ct: An array of unique ciphertext handles is requested for decryption. These are uint256 values derived from unwrapping the unique ciphertext handles provided, such as euint4, euint8, euint16, euint32, euint64, ebool, eaddress, and ebytes256.
CallbackSelector: The function selector for the callback function, which the Gateway contract will call once the relayer fulfills the decryption request.
msgValue : The amount of native tokens to be sent to the calling contract upon fulfillment, i.e., when the callback is returned with the decryption results.
maxTimestamp : The time after which the callback will not be accepted.
requestId : The requestId is returned by requestDecryption and can be useful for providing data in the callback function.
passSignaturesToCaller : If set to false, the callback function does not require signatures to accompany the decrypted value. If set to true, the callback function will include signatures from the KMS, removing the dependency on trusting the Gateway.
There are two ways to pass data to the callback function. Depending on the amount of data, you can decide which method suits you best.
Predefined functions: If you need to pass a few arguments, you can use our predefined functions. A small snippet demonstrating how to use them is shown below.
You can find a list of all predefined functions we support, including both addParams() and getParams() at the following link.
mapping (address=>uint8) public userAddressToRandomNumber; functiondecryptRandomNumber(address userAddress) public { euint8 randomNumber = TFHE.randEuint8(); TFHE.allow(randomNumber,address(this));uint256[] memory cts =newuint256[](1); cts[0] = Gateway.toUint256(randomNumber); uint256 requestId = Gateway.requestDecryption(cts, this.myCustomCallback.selector, 0, block.timestamp + 100, false);
// Adding the user address to the request parametersaddParamsAddress(requestId, userAddress);}functionmyCustomCallback(uint256 requestId,uint8 decryptedInput) publiconlyGatewayreturns (bool) {// Retrieving parameters using the request IDaddress[] memory params =getParamsAddress(requestId); userAddressToRandomNumber[params[0]] = decryptedInput;returntrue;}
Custom Data Holder for Callback Functions: Suppose you have structured data that you want to retain as-is. You can use a combination of mappings and structs to access this data in the callback, as shown below.
structCallbackData {address userAddress;uint8 someNumber;uint256 timestamp;string message; }mapping(uint256=> CallbackData) public requestIdToData;functiondecryptRandomNumber(uint8 someNumber,stringmemory message) public { euint8 randomNumber = TFHE.randEuint8(); TFHE.allow(randomNumber,address(this));uint256[] memory cts =newuint256[](1); cts[0] = Gateway.toUint256(randomNumber); uint256 requestId = Gateway.requestDecryption(cts, this.myCustomCallback.selector, 0, block.timestamp + 100, false);
// Adding the user address to the request parameters requestIdToData[requestId] =CallbackData({ userAddress: msg.sender, someNumber: someNumber, timestamp: block.timestamp, message: message });}functionmyCustomCallback(uint256 requestId,uint8 decryptedInput) publiconlyGatewayreturns (bool) {// Retrieving parameters using the request ID CallbackData memory data = requestIdToData[requestId];// access data and do computation here delete requestIdToData[requestId];returntrue;}