Skip to content

Commit

Permalink
feat: FHEPayment v0
Browse files Browse the repository at this point in the history
  • Loading branch information
jatZama committed Aug 27, 2024
1 parent c75e191 commit 7730752
Show file tree
Hide file tree
Showing 44 changed files with 1,776 additions and 347 deletions.
3 changes: 3 additions & 0 deletions codegen/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { mkdirSync, writeFileSync } from 'fs';

import { ALL_OPERATORS, Network, SUPPORTED_BITS, checks, networkCodegenContext } from './common';
import operatorsPrices from './operatorsPrices.json';
import { generateFHEPayment } from './payments';
import * as t from './templates';
import * as testgen from './testgen';

Expand All @@ -15,6 +17,7 @@ function generateAllFiles() {
writeFileSync('lib/Impl.sol', t.implSol(context, operators));
writeFileSync('lib/TFHE.sol', tfheSolSource);
writeFileSync('lib/FhevmLib.sol', t.fhevmLibSol(operators));
writeFileSync('lib/FHEPayment.sol', generateFHEPayment(operatorsPrices));
mkdirSync('examples/tests', { recursive: true });
ovShards.forEach((os) => {
writeFileSync(`examples/tests/TFHETestSuite${os.shardNumber}.sol`, testgen.generateSmartContract(os));
Expand Down
119 changes: 119 additions & 0 deletions codegen/operatorsPrices.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
{
"fheAdd": {
"binary": true,
"scalar": { "1": 65000, "2": 94000, "3": 133000, "4": 162000, "5": 188000 },
"nonScalar": { "1": 65000, "2": 94000, "3": 133000, "4": 162000, "5": 188000 }
},
"fheSub": {
"binary": true,
"scalar": { "1": 65000, "2": 94000, "3": 133000, "4": 162000, "5": 188000 },
"nonScalar": { "1": 65000, "2": 94000, "3": 133000, "4": 162000, "5": 188000 }
},
"fheMul": {
"binary": true,
"scalar": { "1": 88000, "2": 159000, "3": 208000, "4": 264000, "5": 356000 },
"nonScalar": { "1": 150000, "2": 197000, "3": 262000, "4": 359000, "5": 641000 }
},
"fheDiv": { "binary": true, "scalar": { "1": 139000, "2": 238000, "3": 314000, "4": 398000, "5": 584000 } },
"fheRem": { "binary": true, "scalar": { "1": 286000, "2": 460000, "3": 622000, "4": 805000, "5": 1095000 } },
"fheBitAnd": {
"binary": true,
"nonScalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000 }
},
"fheBitOr": {
"binary": true,
"nonScalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000 }
},
"fheBitXor": {
"binary": true,
"nonScalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000 }
},
"fheShl": {
"binary": true,
"scalar": { "1": 35000, "2": 35000, "3": 35000, "4": 35000, "5": 38000 },
"nonScalar": { "1": 116000, "2": 133000, "3": 153000, "4": 183000, "5": 227000 }
},
"fheShr": {
"binary": true,
"scalar": { "1": 35000, "2": 35000, "3": 35000, "4": 35000, "5": 38000 },
"nonScalar": { "1": 116000, "2": 133000, "3": 153000, "4": 183000, "5": 227000 }
},
"fheRotl": {
"binary": true,
"scalar": { "1": 35000, "2": 35000, "3": 35000, "4": 35000, "5": 38000 },
"nonScalar": { "1": 116000, "2": 133000, "3": 153000, "4": 183000, "5": 227000 }
},
"fheRotr": {
"binary": true,
"scalar": { "1": 35000, "2": 35000, "3": 35000, "4": 35000, "5": 38000 },
"nonScalar": { "1": 116000, "2": 133000, "3": 153000, "4": 183000, "5": 227000 }
},
"fheEq": {
"binary": true,
"scalar": { "1": 51000, "2": 53000, "3": 54000, "4": 82000, "5": 86000, "7": 90000, "11": 300000 },
"nonScalar": { "1": 51000, "2": 53000, "3": 54000, "4": 82000, "5": 86000, "7": 90000, "11": 300000 }
},
"fheNe": {
"binary": true,
"scalar": { "1": 51000, "2": 53000, "3": 54000, "4": 82000, "5": 86000, "7": 90000, "11": 300000 },
"nonScalar": { "1": 51000, "2": 53000, "3": 54000, "4": 82000, "5": 86000, "7": 90000, "11": 300000 }
},
"fheGe": {
"binary": true,
"scalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000 },
"nonScalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000 }
},
"fheGt": {
"binary": true,
"scalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000 },
"nonScalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000 }
},
"fheLe": {
"binary": true,
"scalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000 },
"nonScalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000 }
},
"fheLt": {
"binary": true,
"scalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000 },
"nonScalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000 }
},
"fheMin": {
"binary": true,
"scalar": { "1": 121000, "2": 128000, "3": 150000, "4": 164000, "5": 192000 },
"nonScalar": { "1": 121000, "2": 128000, "3": 153000, "4": 183000, "5": 210000 }
},
"fheMax": {
"binary": true,
"scalar": { "1": 121000, "2": 128000, "3": 150000, "4": 164000, "5": 192000 },
"nonScalar": { "1": 121000, "2": 128000, "3": 153000, "4": 183000, "5": 210000 }
},
"fheNeg": {
"binary": false,
"types": { "1": 60000, "2": 95000, "3": 131000, "4": 160000, "5": 199000 }
},
"fheNot": {
"binary": false,
"types": { "0": 30000, "1": 33000, "2": 34000, "3": 35000, "4": 36000, "5": 37000 }
},
"cast": {
"binary": false,
"types": { "1": 200, "2": 200, "3": 200, "4": 200, "5": 200 }
},
"trivialEncrypt": {
"binary": false,
"types": { "0": 100, "1": 100, "2": 100, "3": 200, "4": 300, "5": 600, "7": 700 }
},
"ifThenElse": {
"binary": false,
"types": { "1": 45000, "2": 47000, "3": 47000, "4": 50000, "5": 53000, "7": 80000 }
},
"fheRand": {
"binary": false,
"types": { "2": 100000, "3": 100000, "4": 100000, "5": 100000 }
},
"fheRandBounded": {
"binary": false,
"types": { "2": 100000, "3": 100000, "4": 100000, "5": 100000 }
}
}
121 changes: 121 additions & 0 deletions codegen/payments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
interface PriceData {
[key: string]: {
binary: boolean;
scalar?: { [key: string]: number };
nonScalar?: { [key: string]: number };
types?: { [key: string]: number };
};
}

export function generateFHEPayment(priceData: PriceData): string {
let output = `// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity ^0.8.24;
import "./TFHEExecutorAddress.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
contract FHEPayment {
/// @notice Name of the contract
string private constant CONTRACT_NAME = "FHEPayment";
/// @notice Version of the contract
uint256 private constant MAJOR_VERSION = 0;
uint256 private constant MINOR_VERSION = 1;
uint256 private constant PATCH_VERSION = 0;
address public immutable tfheExecutorAddress = tfheExecutorAdd;
uint256 private constant FHE_GAS_BLOCKLIMIT = 10_000_000;
uint128 private lastBlock;
uint128 private currentBlockConsumption;
mapping(address payer => uint256 depositedAmount) private depositsETH;
function depositETH(address account) external payable {
depositsETH[account] += msg.value;
}
function withdrawETH(uint256 amount, address receiver) external {
depositsETH[msg.sender] -= amount;
(bool success, ) = receiver.call{value: amount}("");
require(success, "Withdrawal failed");
}
function getAvailableDepositsETH(address account) external view returns (uint256) {
return depositsETH[account];
}
function checkIfNewBlock() private {
uint128 lastBlock_ = uint128(block.number);
if (block.number > lastBlock) {
lastBlock = lastBlock_;
currentBlockConsumption = 0;
}
}\n\n`;

for (const [operation, data] of Object.entries(priceData)) {
const functionName = `payFor${operation.charAt(0).toUpperCase() + operation.slice(1)}`;
if (data.binary) {
output += ` function ${functionName}(address payer, uint8 resultType, bytes1 scalarByte) external {
require(msg.sender == tfheExecutorAddress, "Caller must be TFHEExecutor contract");
checkIfNewBlock();
`;
} else {
output += ` function ${functionName}(address payer, uint8 resultType) external {
require(msg.sender == tfheExecutorAddress, "Caller must be TFHEExecutor contract");
`;
}

if (data.scalar && data.nonScalar) {
output += ` if (scalarByte == 0x01) {
${generatePriceChecks(data.scalar)}
} else {
${generatePriceChecks(data.nonScalar)}
}`;
} else if (data.scalar) {
output += ` require(scalarByte == 0x01, "Only scalar operations are supported");`;
output += `${generatePriceChecks(data.scalar)}`;
} else if (data.nonScalar) {
output += ` require(scalarByte == 0x00, "Only non-scalar operations are supported");`;
output += `${generatePriceChecks(data.nonScalar)}`;
} else {
if (data.types) output += `${generatePriceChecks(data.types)}`;
}

output += `require(currentBlockConsumption <= FHE_GAS_BLOCKLIMIT, "FHEGas block limit exceeded");
}\n\n`;
}

return (
output +
` /// @notice Getter for the name and version of the contract
/// @return string representing the name and the version of the contract
function getVersion() external pure returns (string memory) {
return
string(
abi.encodePacked(
CONTRACT_NAME,
" v",
Strings.toString(MAJOR_VERSION),
".",
Strings.toString(MINOR_VERSION),
".",
Strings.toString(PATCH_VERSION)
)
);
}
}`
);
}

function generatePriceChecks(prices: { [key: string]: number }): string {
return Object.entries(prices)
.map(
([resultType, price]) => ` if (resultType == ${resultType}) {
depositsETH[payer] -= ${price};
currentBlockConsumption += ${price};
}`,
)
.join(' else ');
}
Loading

0 comments on commit 7730752

Please sign in to comment.