Skip to content

Commit

Permalink
Remove TFHE.req (#121)
Browse files Browse the repository at this point in the history
* fix(lib): remove requires

* fix(contracts): remove use of `TFHE.req`
  • Loading branch information
tremblaythibaultl authored Sep 6, 2023
1 parent 4125999 commit 7079aa1
Show file tree
Hide file tree
Showing 8 changed files with 13 additions and 54 deletions.
1 change: 0 additions & 1 deletion codegen/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ export const ALL_PRECOMPILES: Precompile[] = [
{ name: 'Verify', code: 66 },
{ name: 'Reencrypt', code: 67 },
{ name: 'FhePubKey', code: 68 },
{ name: 'Require', code: 69 },
{ name: 'LessThanOrEqual', code: 70 },
{ name: 'Subtract', code: 71 },
{ name: 'Multiply', code: 72 },
Expand Down
29 changes: 5 additions & 24 deletions codegen/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,12 +446,6 @@ function unaryOperatorImpl(op: Operator): string {

function tfheCustomMethods(): string {
return `
// Require that the encrypted bool 'b' is true.
// Involves decrypting 'b'.
function req(ebool b) internal view {
Impl.req(ebool.unwrap(b));
}
// Optimistically require that 'b' is true.
//
// This function does not evaluate 'b' at the time of the call.
Expand All @@ -461,10 +455,11 @@ function tfheCustomMethods(): string {
// gas cost, as if all optimistic requires were true. Yet, the transaction will be
// reverted at the end if any of the optimisic requires were false.
//
// Exceptions to above rule are encrypted requires via TFHE.req() and decryption via
// TFHE.decrypt(). If either of them are encountered and if optimistic requires have been
// used before in the txn, the optimisic requires will be immediately evaluated. Rationale is
// that we want to avoid decrypting a non-optimistic require or a value if the txn is about
// Exceptions to above rule are reencryptions and decryptions via
// TFHE.reencrypt() and TFHE.decrypt(), respectively. If either of them
// are encountered and if optimistic requires have been used before in the
// txn, the optimisic requires will be immediately evaluated. Rationale is
// that we want to avoid decrypting or reencrypting a value if the txn is about
// to fail and be reverted anyway at the end. Checking immediately and reverting on the spot
// would avoid unnecessary decryptions.
//
Expand Down Expand Up @@ -692,20 +687,6 @@ function implCustomMethods(): string {
result = uint256(output[0]);
}
function req(uint256 ciphertext) internal view {
bytes32[1] memory input;
input[0] = bytes32(ciphertext);
uint256 inputLen = 32;
// Call the require precompile.
uint256 precompile = Precompiles.Require;
assembly {
if iszero(staticcall(gas(), precompile, input, inputLen, 0, 0)) {
revert(0, 0)
}
}
}
function decrypt(uint256 ciphertext) internal view returns(uint256 result) {
bytes32[1] memory input;
input[0] = bytes32(ciphertext);
Expand Down
4 changes: 2 additions & 2 deletions contracts/BlindAuction.sol
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ contract BlindAuction is EIP712WithModifier {
// Claim the object. Succeeds only if the caller has the highest bid.
function claim() public onlyAfterEnd {
require(!objectClaimed);
TFHE.req(TFHE.le(highestBid, bids[msg.sender]));
require(TFHE.decrypt(TFHE.le(highestBid, bids[msg.sender])));

objectClaimed = true;
bids[msg.sender] = TFHE.NIL32;
Expand All @@ -137,7 +137,7 @@ contract BlindAuction is EIP712WithModifier {
function withdraw() public onlyAfterEnd {
euint32 bidValue = bids[msg.sender];
if (!objectClaimed) {
TFHE.req(TFHE.lt(bidValue, highestBid));
require(TFHE.decrypt(TFHE.lt(bidValue, highestBid)));
}
tokenContract.transfer(msg.sender, bidValue);
bids[msg.sender] = TFHE.NIL32;
Expand Down
4 changes: 2 additions & 2 deletions contracts/EncryptedERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ contract EncryptedERC20 is EIP712WithModifier {

function _updateAllowance(address owner, address spender, euint32 amount) internal {
euint32 currentAllowance = _allowance(owner, spender);
TFHE.req(TFHE.le(amount, currentAllowance));
require(TFHE.decrypt(TFHE.le(amount, currentAllowance)));
_approve(owner, spender, TFHE.sub(currentAllowance, amount));
}

// Transfers an encrypted amount.
function _transfer(address from, address to, euint32 amount) internal {
// Make sure the sender has enough tokens.
TFHE.req(TFHE.le(amount, balances[from]));
require(TFHE.decrypt(TFHE.le(amount, balances[from])));

// Add to the balance of `to` and subract from the balance of `from`.
balances[to] = TFHE.add(balances[to], amount);
Expand Down
4 changes: 2 additions & 2 deletions contracts/OptimisticRequire.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ contract OptimisticRequire {
// Charge less than full gas, because the non-optimistic ciphertext require aborts early.
function reqFalse() public {
// True.
TFHE.req(TFHE.le(ct1, ct2));
require(TFHE.decrypt(TFHE.le(ct1, ct2)));

// False.
TFHE.req(TFHE.lt(ct1, ct2));
require(TFHE.decrypt(TFHE.lt(ct1, ct2)));

// Try to mutate state to pay for gas - we won't reach that point due to the false require.
doWorkToPayGas();
Expand Down
14 changes: 0 additions & 14 deletions lib/Impl.sol
Original file line number Diff line number Diff line change
Expand Up @@ -580,20 +580,6 @@ library Impl {
result = uint256(output[0]);
}

function req(uint256 ciphertext) internal view {
bytes32[1] memory input;
input[0] = bytes32(ciphertext);
uint256 inputLen = 32;

// Call the require precompile.
uint256 precompile = Precompiles.Require;
assembly {
if iszero(staticcall(gas(), precompile, input, inputLen, 0, 0)) {
revert(0, 0)
}
}
}

function decrypt(uint256 ciphertext) internal view returns (uint256 result) {
bytes32[1] memory input;
input[0] = bytes32(ciphertext);
Expand Down
1 change: 0 additions & 1 deletion lib/Precompiles.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ library Precompiles {
uint256 public constant Verify = 66;
uint256 public constant Reencrypt = 67;
uint256 public constant FhePubKey = 68;
uint256 public constant Require = 69;
uint256 public constant LessThanOrEqual = 70;
uint256 public constant Subtract = 71;
uint256 public constant Multiply = 72;
Expand Down
10 changes: 2 additions & 8 deletions lib/TFHE.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2483,12 +2483,6 @@ library TFHE {
return euint32.wrap(Impl.not(euint32.unwrap(value)));
}

// Require that the encrypted bool 'b' is true.
// Involves decrypting 'b'.
function req(ebool b) internal view {
Impl.req(ebool.unwrap(b));
}

// Optimistically require that 'b' is true.
//
// This function does not evaluate 'b' at the time of the call.
Expand All @@ -2498,10 +2492,10 @@ library TFHE {
// gas cost, as if all optimistic requires were true. Yet, the transaction will be
// reverted at the end if any of the optimisic requires were false.
//
// Exceptions to above rule are encrypted requires via TFHE.req() and decryption via
// Exceptions to above rule are reencryptions and decryptions via
// TFHE.decrypt(). If either of them are encountered and if optimistic requires have been
// used before in the txn, the optimisic requires will be immediately evaluated. Rationale is
// that we want to avoid decrypting a non-optimistic require or a value if the txn is about
// that we want to avoid decrypting or reencrypting a value if the txn is about
// to fail and be reverted anyway at the end. Checking immediately and reverting on the spot
// would avoid unnecessary decryptions.
//
Expand Down

0 comments on commit 7079aa1

Please sign in to comment.