Skip to content

Commit 1bbab83

Browse files
authored
docs(common): add section handling ACL with reorgs for high-value case (#376)
* docs(common): add section handling ACL with reorgs for high-value case * docs(common): fixed typos in reorg section
1 parent 8655ae0 commit 1bbab83

2 files changed

Lines changed: 67 additions & 0 deletions

File tree

docs/solidity-guides/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
- [Encrypted Inputs](inputs.md)
2323
- [Access Control List](acl/README.md)
2424
- [ACL examples](acl/acl_examples.md)
25+
- [Reorgs handling](acl/reorgs_handling.md)
2526
- [Logics](<README (1).md>)
2627
- [Branching](logics/conditions.md)
2728
- [Dealing with branches and conditions](logics/loop.md)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Reorgs handling
2+
3+
Since ACL events are propagated from the FHEVM host chain to the [Gateway](../../protocol/architecture/gateway.md) immediately after being included in a block, dApp developers must take special care when encrypted information is critically important. For example, if an encrypted handle conceals the private key of a Bitcoin wallet holding significant funds, we need to ensure that this information cannot inadvertently leak to the wrong person due to a reorg on the FHEVM host chain. Therefore, it's the responsibility of dApp developers to prevent such scenarios by implementing a two-step ACL authorization process with a timelock between the request and the ACL call.
4+
5+
---
6+
7+
## Simple example: Handling reorg risk on Ethereum
8+
9+
On Ethereum, a reorg can be up to 95 slots deep in the worst case, so waiting for more than 95 blocks should ensure that a previously sent transaction has been finalized—unless more than 1/3 of the nodes are malicious and willing to lose their stake, which is highly improbable.
10+
11+
**Instead of writing this contract:**
12+
13+
```solidity
14+
contract PrivateKeySale {
15+
euint256 privateKey;
16+
bool isAlreadyBought = false;
17+
18+
constructor(externalEuint256 _privateKey, bytes inputProof) {
19+
privateKey = FHE.fromExternal(_privateKey, inputProof);
20+
FHE.allowThis(privateKey);
21+
}
22+
23+
function buyPrivateKey() external payable {
24+
require(msg.value == 1 ether, "Must pay 1 ETH");
25+
require(!isBought, "Private key already bought");
26+
isBought = true;
27+
FHE.allow(encryptedPrivateKey, msg.sender);
28+
}
29+
}
30+
```
31+
32+
Since the `privateKey`` encrypted variable contains critical information, we don't want to mistakenly leak it for free if a reorg occurs. This could happen in the previous example because we immediately grant authorization to the buyer in the same transaction that processes the sale.
33+
34+
**We recommend writing something like this instead:**
35+
36+
```solidity
37+
contract PrivateKeySale {
38+
euint256 privateKey;
39+
bool isAlreadyBought = false;
40+
uint256 blockWhenBought = 0;
41+
address buyer;
42+
43+
constructor(externalEuint256 _privateKey, bytes inputProof) {
44+
privateKey = FHE.fromExternal(_privateKey, inputProof);
45+
FHE.allowThis(privateKey);
46+
}
47+
48+
function buyPrivateKey() external payable {
49+
require(msg.value == 1 ether, "Must pay 1 ETH");
50+
require(!isBought, "Private key already bought");
51+
isBought = true;
52+
blockWhenBought = block.number;
53+
buyer = msg.sender;
54+
}
55+
56+
function requestACL() external {
57+
require(isBought, "Private key has not been bought yet");
58+
require(block.number > blockWhenBought+95, "Too early to request ACL, risk of reorg");
59+
FHE.allow(privateKey, buyer);
60+
}
61+
}
62+
```
63+
64+
This approach ensures that at least 96 blocks have elapsed between the transaction that purchases the private key and the transaction that authorizes the buyer to decrypt it.
65+
66+
*Note:* This type of contract worsens the user experience by adding a timelock before users can decrypt data, so it should be used sparingly: only when leaked information could be critically important and high-value.

0 commit comments

Comments
 (0)