Overview
Decryption is the process of converting encrypted data back into its original form. In the context of Fully Homomorphic Encryption (FHE), decryption allows for the retrieval of results after performing computations on encrypted data. Decryption in CoFHE is a multi-step process that involves both offchain and onchain components:- A client requests decryption offchain and receives the plaintext along with a Threshold Network signature.
- The plaintext and signature are submitted onchain, where the contract publishes or verifies the result.
Decryption Methods: Transaction vs View
CoFHE provides two primary ways to perform decryption, each suited for different use cases:1. Decrypt for Transaction (decryptForTx)
The client calls decryptForTx(ctHash) offchain to obtain the plaintext and a Threshold Network signature. These are then submitted onchain via FHE.publishDecryptResult or FHE.verifyDecryptResult, making the result verifiable by the contract.
Common examples:
- Unshield a confidential token: reveal the encrypted amount so the contract can finalize the public transfer.
- Finalize a private auction / game move: bids or moves are submitted encrypted, and the winner is revealed later in a verifiable way.
2. Decrypt for View (decryptForView)
The client calls decryptForView offchain to obtain the plaintext for display in a UI. No onchain transaction or signature is needed.
Common examples:
- Displaying a user’s confidential balance in a wallet UI.
- Showing the current state of an encrypted value without revealing it onchain.
Use
decryptForTx when you need to act on the decrypted value in a smart contract. Use decryptForView when you only need to display the value in a UI.3. Client-Published Decryption (Signature-Verified)
The client decrypts offchain viadecryptForTx, receives the plaintext result along with an ECDSA signature from the Threshold Network’s Dispatcher, and then publishes the result onchain by calling FHE.publishDecryptResult(). The TaskManager verifies the signature onchain before storing the result.
This combines the best of both worlds: the client controls when the result lands onchain, while the contract can still use the decrypted value.
The signature cryptographically proves the result came from the authorized Threshold Network. No trust in the publisher is required. Anyone holding a valid signature can submit it.
Comparison Table
The Decryption Flow
Step 1: Grant decryption permissions (onchain)
Before anyone can request decryption, the ciphertext handle must have the appropriate ACL permissions. Use one of the following in your contract:FHE.allowPublic(ctHash): anyone can request decryption (common for unshield flows)FHE.allow(ctHash, address): only a specific address can request decryptionFHE.allowSender(ctHash): onlymsg.sendercan request decryption
See Access Control for the full list of permission methods, including
FHE.allowPublic().Step 2: Request decryption offchain (client-side)
The client callsdecryptForTx(ctHash) to obtain the plaintext and a Threshold Network signature. Choose the ACP mode that matches the contract’s ACL policy:
decryptForTx always returns the plaintext as a bigint. Your contract determines whether that value is interpreted as uint32, uint64, etc.Step 3: Publish or verify onchain
Submit the plaintext and signature to your contract. You have two options:Option A: FHE.publishDecryptResult
Publishes the decrypted value onchain, making it available for any contract to read.
Option B: FHE.verifyDecryptResult
Verifies the signature without publishing the result globally. Use this when your contract only needs to confirm the plaintext is authentic.
Full Example Contract
Here’s a complete example showing the new decryption flow in an auction contract:Batch Client-Published Decryption
Signature Verification Functions
When using client-published decryption, two verification functions are available:
Both functions accept type-specific overloads for
ebool, euint8, euint16, euint32, euint64, euint128, and eaddress.
Best Practices
Use allowPublic for values meant to be revealed
When a value is intended to become public (e.g. unshielding, auction reveals), use
FHE.allowPublic() so anyone can trigger the decryption without needing an ACP.Check Access Control Before Decrypting
Ensure only authorized parties can request decryption. Use
FHE.allow() or FHE.allowSender() for restricted access. See Access Control.Choose the right onchain method
Use
FHE.publishDecryptResult when you want the result stored publicly onchain. Use FHE.verifyDecryptResult when you only need to confirm the plaintext is authentic without publishing it.Use decryptForView for UI-only reads
If you only need to display a value in your UI and don’t need an onchain-verifiable signature, use
decryptForView instead of decryptForTx to avoid unnecessary onchain transactions.Common Pitfalls
- Missing ACL permissions: If no
allow*was called for the ciphertext handle, decryption requests will be denied. Make sure to grant permissions before the client requests decryption. - ACP mode must be selected: When using
decryptForTx, you must call exactly one of.withACP(...)or.withoutACP()before.execute(). - Wrong chain/account: ACPs are scoped to
chainId + account. If you get an ACL or ACP error, double-check you’re connected to the expected chain and account. - Type mismatch:
decryptedValueis always abigint. If your Solidity function expects a smaller integer type (e.g.uint32), make sure the value is within range.
Related Topics
- Learn about access control requirements in Access Control
- Understand asynchronous operations in Data Evaluation
- Explore the decryption request flow in Decryption Request Flow