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 off-chain and on-chain components:- A client requests decryption off-chain and receives the plaintext along with a Threshold Network signature.
- The plaintext and signature are submitted on-chain, 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) off-chain to obtain the plaintext and a Threshold Network signature. These are then submitted on-chain 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 off-chain to obtain the plaintext for display in a UI. No on-chain 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 on-chain.
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.Comparison Table
| Method | Visibility | Gas Cost | Smart Contract Usable | Best For |
|---|---|---|---|---|
decryptForTx | Public (once published on-chain) | Gas for the publish/verify tx | Yes | Public results, contract logic |
decryptForView | Private (off-chain only) | None | No | UI display, confidential data |
The Decryption Flow
Step 1: Grant decryption permissions (on-chain)
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 off-chain (client-side)
The client callsdecryptForTx(ctHash) to obtain the plaintext and a Threshold Network signature. Choose the permit 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 on-chain
Submit the plaintext and signature to your contract. You have two options:Option A: FHE.publishDecryptResult
Publishes the decrypted value on-chain, 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: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 a permit.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 on-chain method
Use
FHE.publishDecryptResult when you want the result stored publicly on-chain. 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 on-chain-verifiable signature, use
decryptForView instead of decryptForTx to avoid unnecessary on-chain 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. - Permit mode must be selected: When using
decryptForTx, you must call exactly one of.withPermit(...)or.withoutPermit()before.execute(). - Wrong chain/account: Permits are scoped to
chainId + account. If you get an ACL/permit 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