@cofhe/mock-contracts 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @cofhe/mock-contracts Changelog
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6f7a4c5: Resolve the Task Manager through the `CoFHEAddressBook` (`@fhenixprotocol/cofhe-contracts@1.0.0`). **Breaking:** `TASK_MANAGER_ADDRESS` is removed from `@cofhe/sdk`. Use `getTaskManagerAddress(publicClient)`, which reads `getTm(TASK_MANAGER_ID)` from the book at `COFHE_ADDRESS_BOOK_ADDRESS` (both exported) and caches the result per chain. If the chain has no book, or the id is unset, it throws `TASK_MANAGER_UNRESOLVED`. `verifyDecryptResult`, the ACL/ACP lookups and `useCofheEnabled` / `useCofheReadDecryptionResults` now resolve the Task Manager this way. `@cofhe/react` adds `useCofheTaskManagerAddress()`.
8
+
9
+ Mocks: a new `MockCoFHEAddressBook` is deployed at FHE.sol's `COFHE_ADDRESS_BOOK`, and `MockTaskManager` moves to `MOCKS_TASK_MANAGER_ADDRESS` (`0x…5000`) and is registered in the book. `MockACL` now stores its Task Manager (`setTaskManager` / `getTaskManagerAddress`) instead of reading a constant, so its `TASK_MANAGER_ADDRESS_()` getter is gone. All three plugins deploy and wire the book. Hardhat 2 exposes `hre.cofhe.mocks.getMockCoFHEAddressBook()`, Hardhat 3 exposes `conn.cofhe.mocks.MockCoFHEAddressBook`, and Foundry exposes `CofheTest.mockAddressBook`. Contracts must be built against `@fhenixprotocol/cofhe-contracts@1.0.0` or later (the hardhat plugin's peer range is now `>=1.0.0`). Each FHE op now makes one extra `getTm` call on the book, as it does on real networks, so expect slightly higher gas numbers.
10
+
11
+ ### Patch Changes
12
+
13
+ - ccb7b68: Realistic gas reporting for mocks. Under Foundry, mock-only work is now excluded from gas metering by default (opt out with `mockTaskManager.setMockGasExcluded(false)`), so expect `forge snapshot` numbers to drop. Under Hardhat, mock transactions emit `MockGasConsumed` events (extra receipt logs), and the plugins add `getAdjustedGasUsed(receipt)` / `getAdjustedGasBreakdown(receipt)` plus an opt-in `cofhe.gasSummary` report.
14
+
3
15
  ## 0.7.1
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -10,6 +10,7 @@ A mock smart contract library for testing CoFHE (Confidential Computing Framewor
10
10
  ## Features
11
11
 
12
12
  - Mock implementations of core CoFHE contracts:
13
+ - MockCoFHEAddressBook (deployed at FHE.sol's `COFHE_ADDRESS_BOOK`, resolves the TaskManager)
13
14
  - MockTaskManager
14
15
  - MockThresholdNetwork
15
16
  - MockZkVerifier
@@ -137,6 +138,15 @@ When interacting with CoFHE this request is routed to the Threshold Network, whi
137
138
 
138
139
  When working with the mocks, the `cofheClient` instead queries the `MockThresholdNetwork` contract, which verifies the request `acp` and returns the decrypted result.
139
140
 
141
+ ### Gas
142
+
143
+ Because the mocks replicate the off-chain FHE computation on-chain (plaintext math, mock storage writes, logging), transactions consume more gas than they would on a real CoFHE network. The mocks account for this in two ways:
144
+
145
+ - **Foundry**: when gas exclusion is enabled (`setMockGasExcluded(true)` — the foundry plugin's `deployMocks()` does this automatically), the mock-only work runs between `pauseGasMetering` / `resumeGasMetering` cheatcodes, so forge's reported gas approximates real-network cost. Requires cheatcode access (`vm.allowCheatcodes(taskManagerAddress)`) and forge ≥ 1.0; without either, execution silently stays metered.
146
+ - **Everywhere else** (Hardhat, anvil): `MockTaskManager` measures each block of mock-only work with `gasleft()` and emits a `MockGasConsumed(uint256)` event. Summing these events from a receipt and subtracting from `gasUsed` yields the adjusted cost — the hardhat plugins expose this as `getAdjustedGasUsed(receipt)` / `getAdjustedGasBreakdown(receipt)` and an opt-in `gasSummary` table.
147
+
148
+ `eth_estimateGas` is never adjusted: the mock work really executes, so transactions still need the raw gas limit.
149
+
140
150
  ### Using Foundry
141
151
 
142
152
  Use [`@cofhe/foundry-plugin`](../foundry-plugin/README.md), which builds on these mocks. Inherit its
@@ -3,7 +3,6 @@ pragma solidity >=0.8.19 <0.9.0;
3
3
 
4
4
  import { Strings } from '@openzeppelin/contracts/utils/Strings.sol';
5
5
  import { MockPermissioned, ACP, SCOPE_GLOBAL, SCOPE_CONTRACT, SCOPE_HANDLES } from './Permissioned.sol';
6
- import { TASK_MANAGER_ADDRESS } from '@fhenixprotocol/cofhe-contracts/FHE.sol';
7
6
 
8
7
  /**
9
8
  * @title ACL
@@ -32,6 +31,9 @@ contract MockACL is MockPermissioned {
32
31
  /// @param receiver Address the share would have been directed at.
33
32
  error NotShared(uint256 handle, address receiver);
34
33
 
34
+ /// @notice Returned when the TaskManager address being set is zero.
35
+ error InvalidTaskManagerAddress();
36
+
35
37
  /// @notice Returned when a share is pending but was written by a different party.
36
38
  /// @param expected Sharer the receiver named.
37
39
  /// @param actual Sharer recorded in the slot.
@@ -53,6 +55,9 @@ contract MockACL is MockPermissioned {
53
55
  /// @notice Emitted when the share registry address is updated (zero = unset).
54
56
  event ShareRegistryUpdated(address oldAddress, address newAddress);
55
57
 
58
+ /// @notice Emitted when the TaskManager address is updated.
59
+ event TaskManagerUpdated(address oldAddress, address newAddress);
60
+
56
61
  /// @custom:storage-location erc7201:cofhe.storage.ACL
57
62
  struct ACLStorage {
58
63
  mapping(uint256 handle => bool isGlobal) globalHandles;
@@ -62,6 +67,7 @@ contract MockACL is MockPermissioned {
62
67
  /// @dev ACP infrastructure addresses served to SDKs (appended fields — do not reorder)
63
68
  address defaultRevokerContract;
64
69
  address shareRegistry;
70
+ address taskManager;
65
71
  }
66
72
 
67
73
  /// @notice Name of the contract.
@@ -76,9 +82,6 @@ contract MockACL is MockPermissioned {
76
82
  /// @notice Patch version of the contract.
77
83
  uint256 private constant PATCH_VERSION = 0;
78
84
 
79
- /// @notice TaskManagerAddress address.
80
- address public constant TASK_MANAGER_ADDRESS_ = TASK_MANAGER_ADDRESS;
81
-
82
85
  /// @dev keccak256(abi.encode(uint256(keccak256("cofhe.storage.ACL")) - 1)) & ~bytes32(uint256(0xff))
83
86
  bytes32 private constant ACL_SLOT =
84
87
  keccak256(abi.encode(uint256(keccak256('cofhe.storage.ACL')) - 1)) & ~bytes32(uint256(0xff));
@@ -103,7 +106,7 @@ contract MockACL is MockPermissioned {
103
106
  * @param requester Address of the account giving the permissions.
104
107
  */
105
108
  function allow(uint256 handle, address account, address requester) public virtual {
106
- if (msg.sender != TASK_MANAGER_ADDRESS_) {
109
+ if (msg.sender != _taskManager()) {
107
110
  revert DirectAllowForbidden(msg.sender);
108
111
  }
109
112
 
@@ -122,7 +125,7 @@ contract MockACL is MockPermissioned {
122
125
  * @param requester Address of the account giving the permissions.
123
126
  */
124
127
  function allowGlobal(uint256 handle, address requester) public virtual {
125
- if (msg.sender != TASK_MANAGER_ADDRESS_) {
128
+ if (msg.sender != _taskManager()) {
126
129
  revert DirectAllowForbidden(msg.sender);
127
130
  }
128
131
 
@@ -140,7 +143,7 @@ contract MockACL is MockPermissioned {
140
143
  * @param handlesList List of handles.
141
144
  */
142
145
  function allowForDecryption(uint256[] memory handlesList, address requester) public virtual {
143
- if (msg.sender != TASK_MANAGER_ADDRESS_) {
146
+ if (msg.sender != _taskManager()) {
144
147
  revert DirectAllowForbidden(msg.sender);
145
148
  }
146
149
 
@@ -167,11 +170,11 @@ contract MockACL is MockPermissioned {
167
170
  * @param requester Address of the requester.
168
171
  */
169
172
  function allowTransient(uint256 handle, address account, address requester) public virtual {
170
- if (msg.sender != TASK_MANAGER_ADDRESS_) {
173
+ if (msg.sender != _taskManager()) {
171
174
  revert DirectAllowForbidden(msg.sender);
172
175
  }
173
176
 
174
- if (!isAllowed(handle, requester) && requester != TASK_MANAGER_ADDRESS_) {
177
+ if (!isAllowed(handle, requester) && requester != _taskManager()) {
175
178
  revert SenderNotAllowed(requester);
176
179
  }
177
180
 
@@ -217,14 +220,14 @@ contract MockACL is MockPermissioned {
217
220
  * @notice Grants `receiver` transient access to `handle` and records `sharer` as the
218
221
  * party that handed it over, for the duration of this transaction.
219
222
  * @dev The caller must be the Task Manager contract.
220
- * @dev Stricter than allowTransient: there is no TASK_MANAGER_ADDRESS bypass, since
223
+ * @dev Stricter than allowTransient: there is no TaskManager bypass, since
221
224
  * nothing shares on the Task Manager's own behalf.
222
225
  * @param handle Handle.
223
226
  * @param sharer Address handing the handle over.
224
227
  * @param receiver Address the handle is being handed to.
225
228
  */
226
229
  function shareCtHash(uint256 handle, address sharer, address receiver) public virtual {
227
- if (msg.sender != TASK_MANAGER_ADDRESS_) {
230
+ if (msg.sender != _taskManager()) {
228
231
  revert DirectAllowForbidden(msg.sender);
229
232
  }
230
233
 
@@ -247,7 +250,7 @@ contract MockACL is MockPermissioned {
247
250
  * @param receiver Address consuming the share.
248
251
  */
249
252
  function receiveCtHash(uint256 handle, address expectedSharer, address receiver) public virtual {
250
- if (msg.sender != TASK_MANAGER_ADDRESS_) {
253
+ if (msg.sender != _taskManager()) {
251
254
  revert DirectAllowForbidden(msg.sender);
252
255
  }
253
256
 
@@ -270,7 +273,7 @@ contract MockACL is MockPermissioned {
270
273
  * @param delegateeContract Delegatee contract.
271
274
  */
272
275
  function delegateAccount(address delegatee, address delegateeContract) public virtual {
273
- if (msg.sender != TASK_MANAGER_ADDRESS_) {
276
+ if (msg.sender != _taskManager()) {
274
277
  revert DirectAllowForbidden(msg.sender);
275
278
  }
276
279
  if (delegateeContract == msg.sender) {
@@ -328,7 +331,7 @@ contract MockACL is MockPermissioned {
328
331
  * @return taskManagerAddress Address of the TaskManager.
329
332
  */
330
333
  function getTaskManagerAddress() public view virtual returns (address) {
331
- return TASK_MANAGER_ADDRESS_;
334
+ return _taskManager();
332
335
  }
333
336
 
334
337
  /**
@@ -378,7 +381,7 @@ contract MockACL is MockPermissioned {
378
381
  * Account Abstraction when bundling several UserOps calling the TaskManagerCoprocessor.
379
382
  */
380
383
  function cleanTransientStorage() external virtual {
381
- if (msg.sender != TASK_MANAGER_ADDRESS_) {
384
+ if (msg.sender != _taskManager()) {
382
385
  revert DirectAllowForbidden(msg.sender);
383
386
  }
384
387
 
@@ -458,6 +461,21 @@ contract MockACL is MockPermissioned {
458
461
  $.shareRegistry = newAddress;
459
462
  }
460
463
 
464
+ /// @notice Sets the TaskManager allowed to drive this ACL (unrestricted in the mock;
465
+ /// the production setter is onlyRole(DEFAULT_ADMIN_ROLE)).
466
+ function setTaskManager(address newAddress) external {
467
+ if (newAddress == address(0)) {
468
+ revert InvalidTaskManagerAddress();
469
+ }
470
+ ACLStorage storage $ = _getACLStorage();
471
+ emit TaskManagerUpdated($.taskManager, newAddress);
472
+ $.taskManager = newAddress;
473
+ }
474
+
475
+ function _taskManager() private view returns (address) {
476
+ return _getACLStorage().taskManager;
477
+ }
478
+
461
479
  /// @notice V3 (ACP) access check — the scope table.
462
480
  ///
463
481
  /// | condition | result |
@@ -6,6 +6,11 @@ import { FHE } from '@fhenixprotocol/cofhe-contracts/FHE.sol';
6
6
  import { FunctionId, Utils } from '@fhenixprotocol/cofhe-contracts/ICofhe.sol';
7
7
  import { console } from 'hardhat/console.sol';
8
8
 
9
+ /// @dev Foundry/hevm cheatcode address: address(uint160(uint256(keccak256('hevm cheat code')))).
10
+ /// Only reachable when running under forge with cheatcode access granted (vm.allowCheatcodes);
11
+ /// on Hardhat this address has no code and the shim is never enabled.
12
+ address constant CHEATCODE_ADDRESS = 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D;
13
+
9
14
  address constant ZK_VERIFIER_SIGNER_ADDRESS = 0x6E12D8C87503D4287c294f2Fdef96ACd9DFf6bd2;
10
15
  uint256 constant ZK_VERIFIER_SIGNER_PRIVATE_KEY = 49099792800763675079532137679706322989817545357788440619111868498148356080914;
11
16
 
@@ -33,9 +38,27 @@ abstract contract MockCoFHE {
33
38
 
34
39
  bool public logOps = true;
35
40
 
41
+ /// @dev When true, mock-only work (plaintext replication + logging) runs between
42
+ /// pauseGasMetering/resumeGasMetering cheatcodes so it is excluded from forge's
43
+ /// gas accounting, giving gas numbers closer to the real CoFHE task manager.
44
+ /// Only enable under forge AFTER granting this contract cheatcode access
45
+ /// (vm.allowCheatcodes(address(taskManager))); must stay false on Hardhat.
46
+ bool public mockGasExcluded = false;
47
+
36
48
  mapping(uint256 => uint256) public mockStorage;
37
49
  mapping(uint256 => bool) public inMockStorage;
38
50
 
51
+ /// @dev Emitted for each block of mock-only work (op replication, decrypt-task storage,
52
+ /// log building) with the gas it consumed, whenever that work runs metered (i.e. not
53
+ /// under forge's paused gas metering). Tooling sums these per transaction to compute
54
+ /// gas usage excluding mock overhead - see the hardhat plugin's getAdjustedGasUsed.
55
+ event MockGasConsumed(uint256 gas);
56
+
57
+ /// @dev Gas spent emitting MockGasConsumed itself (LOG1 + 32 data bytes + bookkeeping).
58
+ /// It lands after the closing gasleft() read, so it is added back as a constant to
59
+ /// keep the reported figure covering the full mock-only cost.
60
+ uint256 internal constant MOCK_GAS_EVENT_COST = 1030;
61
+
39
62
  error InputNotInMockStorage(uint256 ctHash);
40
63
 
41
64
  // Used internally to check if we missed any operations in the mocks
@@ -49,6 +72,59 @@ abstract contract MockCoFHE {
49
72
  logOps = _logOps;
50
73
  }
51
74
 
75
+ function setMockGasExcluded(bool _mockGasExcluded) public {
76
+ mockGasExcluded = _mockGasExcluded;
77
+ }
78
+
79
+ /// @dev How a mock-only block is being accounted for.
80
+ /// MEASURE - metering is live: measure with gasleft() and emit MockGasConsumed.
81
+ /// PAUSED_BY_MOCK - we paused forge's metering and must resume it afterwards.
82
+ /// ALREADY_UNMETERED - metering was already paused by the caller's own test; leave it
83
+ /// untouched (the mock work is unmetered either way) and emit nothing.
84
+ enum MockGasMode {
85
+ MEASURE,
86
+ PAUSED_BY_MOCK,
87
+ ALREADY_UNMETERED
88
+ }
89
+
90
+ /// @dev True while forge's gas metering is paused: gasleft() is frozen, so two consecutive
91
+ /// reads are equal. While metered they differ by the cost of the second GAS opcode.
92
+ /// (Foundry has no query cheatcode for this state.)
93
+ function _isGasMeteringPaused() internal view returns (bool) {
94
+ uint256 a = gasleft();
95
+ uint256 b = gasleft();
96
+ return a == b;
97
+ }
98
+
99
+ /// @dev Opens a mock-only block. Under forge (detected by code at the cheatcode address -
100
+ /// forge plants a marker byte there, other environments have none) with exclusion
101
+ /// enabled, pauses gas metering unless the caller's test already paused it - never
102
+ /// steal a pause we don't own, or `_mockGasTrackEnd` would resume metering out from
103
+ /// under the user's own measurement region. Everywhere else, records gasleft() so the
104
+ /// block's cost can be reported via MockGasConsumed.
105
+ /// Only wrap code that cannot revert - a revert inside the block would skip
106
+ /// `_mockGasTrackEnd` and leak paused metering (see sendEventCreated's trampoline
107
+ /// for the revert-safe variant).
108
+ function _mockGasTrackStart() internal returns (MockGasMode mode, uint256 startGas) {
109
+ if (mockGasExcluded && CHEATCODE_ADDRESS.code.length > 0) {
110
+ if (_isGasMeteringPaused()) return (MockGasMode.ALREADY_UNMETERED, 0);
111
+ (bool ok, ) = CHEATCODE_ADDRESS.call(abi.encodeWithSignature('pauseGasMetering()'));
112
+ if (ok) return (MockGasMode.PAUSED_BY_MOCK, 0);
113
+ }
114
+ return (MockGasMode.MEASURE, gasleft());
115
+ }
116
+
117
+ /// @dev Closes a mock-only block: resumes metering (if we paused it) or emits the
118
+ /// measured cost. A caller-owned pause is left exactly as we found it.
119
+ function _mockGasTrackEnd(MockGasMode mode, uint256 startGas) internal {
120
+ if (mode == MockGasMode.PAUSED_BY_MOCK) {
121
+ (bool ok, ) = CHEATCODE_ADDRESS.call(abi.encodeWithSignature('resumeGasMetering()'));
122
+ ok;
123
+ } else if (mode == MockGasMode.MEASURE) {
124
+ emit MockGasConsumed(startGas - gasleft() + MOCK_GAS_EVENT_COST);
125
+ }
126
+ }
127
+
52
128
  // Utils
53
129
 
54
130
  function getUintTypeFromHash(uint256 hash) internal pure returns (uint8) {
@@ -224,76 +300,87 @@ abstract contract MockCoFHE {
224
300
  logAllow(operation, ctHash, account);
225
301
  }
226
302
 
303
+ /// @dev Same as MOCK_logAllow, but the log-string building runs excluded from forge gas
304
+ /// metering / reported via MockGasConsumed, like the rest of the mock-only work.
305
+ /// With logging disabled the whole thing is skipped - the residual cost is negligible.
306
+ /// Safe without the revert trampoline: logAllow only formats bounded strings.
307
+ function MOCK_trackedLogAllow(string memory operation, uint256 ctHash, address account) internal {
308
+ if (!logOps) return;
309
+ (MockGasMode mode, uint256 startGas) = _mockGasTrackStart();
310
+ logAllow(operation, ctHash, account);
311
+ _mockGasTrackEnd(mode, startGas);
312
+ }
313
+
227
314
  // Mock functions
228
315
 
229
316
  function MOCK_verifyKeyInStorage(uint256 ctHash) internal view {
230
317
  if (!inMockStorage[ctHash]) revert InputNotInMockStorage(ctHash);
231
318
  }
232
319
 
233
- function MOCK_unaryOperation(uint256 ctHash, string memory operation, uint256 input) internal {
234
- if (opIs(operation, FunctionId.random)) {
320
+ function MOCK_unaryOperation(uint256 ctHash, FunctionId funcId, uint256 input) internal {
321
+ if (funcId == FunctionId.random) {
235
322
  _set(ctHash, uint256(blockhash(block.number - 1)));
236
- logOperation('FHE.random', '', logCtHash(ctHash));
323
+ if (logOps) logOperation('FHE.random', '', logCtHash(ctHash));
237
324
  return;
238
325
  }
239
- if (opIs(operation, FunctionId.cast)) {
326
+ if (funcId == FunctionId.cast) {
240
327
  _set(ctHash, _get(input));
241
- logOperation('FHE.cast', logCtHash(input), logCtHash(ctHash));
328
+ if (logOps) logOperation('FHE.cast', logCtHash(input), logCtHash(ctHash));
242
329
  return;
243
330
  }
244
- if (opIs(operation, FunctionId.not)) {
331
+ if (funcId == FunctionId.not) {
245
332
  bool inputIsTruthy = _get(input) == 1;
246
333
  _set(ctHash, !inputIsTruthy);
247
- logOperation('FHE.not', logCtHash(input), logCtHash(ctHash));
334
+ if (logOps) logOperation('FHE.not', logCtHash(input), logCtHash(ctHash));
248
335
  return;
249
336
  }
250
- if (opIs(operation, FunctionId.square)) {
337
+ if (funcId == FunctionId.square) {
251
338
  unchecked {
252
339
  _set(ctHash, _get(input) * _get(input));
253
340
  }
254
- logOperation('FHE.square', string.concat(logCtHash(input), ' * ', logCtHash(input)), logCtHash(ctHash));
341
+ if (logOps) logOperation('FHE.square', string.concat(logCtHash(input), ' * ', logCtHash(input)), logCtHash(ctHash));
255
342
  return;
256
343
  }
257
- revert InvalidUnaryOperation(operation);
344
+ revert InvalidUnaryOperation(Utils.functionIdToString(funcId));
258
345
  }
259
346
 
260
- function MOCK_twoInputOperation(uint256 ctHash, string memory operation, uint256 input1, uint256 input2) internal {
261
- if (opIs(operation, FunctionId.sub)) {
347
+ function MOCK_twoInputOperation(uint256 ctHash, FunctionId funcId, uint256 input1, uint256 input2) internal {
348
+ if (funcId == FunctionId.sub) {
262
349
  unchecked {
263
350
  _set(ctHash, _get(input1) - _get(input2));
264
351
  }
265
- logOperation('FHE.sub', string.concat(logCtHash(input1), ' - ', logCtHash(input2)), logCtHash(ctHash));
352
+ if (logOps) logOperation('FHE.sub', string.concat(logCtHash(input1), ' - ', logCtHash(input2)), logCtHash(ctHash));
266
353
  return;
267
354
  }
268
- if (opIs(operation, FunctionId.add)) {
355
+ if (funcId == FunctionId.add) {
269
356
  unchecked {
270
357
  _set(ctHash, _get(input1) + _get(input2));
271
358
  }
272
- logOperation('FHE.add', string.concat(logCtHash(input1), ' + ', logCtHash(input2)), logCtHash(ctHash));
359
+ if (logOps) logOperation('FHE.add', string.concat(logCtHash(input1), ' + ', logCtHash(input2)), logCtHash(ctHash));
273
360
  return;
274
361
  }
275
- if (opIs(operation, FunctionId.xor)) {
362
+ if (funcId == FunctionId.xor) {
276
363
  unchecked {
277
364
  _set(ctHash, _get(input1) ^ _get(input2));
278
365
  }
279
- logOperation('FHE.xor', string.concat(logCtHash(input1), ' ^ ', logCtHash(input2)), logCtHash(ctHash));
366
+ if (logOps) logOperation('FHE.xor', string.concat(logCtHash(input1), ' ^ ', logCtHash(input2)), logCtHash(ctHash));
280
367
  return;
281
368
  }
282
- if (opIs(operation, FunctionId.and)) {
369
+ if (funcId == FunctionId.and) {
283
370
  unchecked {
284
371
  _set(ctHash, _get(input1) & _get(input2));
285
372
  }
286
- logOperation('FHE.and', string.concat(logCtHash(input1), ' & ', logCtHash(input2)), logCtHash(ctHash));
373
+ if (logOps) logOperation('FHE.and', string.concat(logCtHash(input1), ' & ', logCtHash(input2)), logCtHash(ctHash));
287
374
  return;
288
375
  }
289
- if (opIs(operation, FunctionId.or)) {
376
+ if (funcId == FunctionId.or) {
290
377
  unchecked {
291
378
  _set(ctHash, _get(input1) | _get(input2));
292
379
  }
293
- logOperation('FHE.or', string.concat(logCtHash(input1), ' | ', logCtHash(input2)), logCtHash(ctHash));
380
+ if (logOps) logOperation('FHE.or', string.concat(logCtHash(input1), ' | ', logCtHash(input2)), logCtHash(ctHash));
294
381
  return;
295
382
  }
296
- if (opIs(operation, FunctionId.div)) {
383
+ if (funcId == FunctionId.div) {
297
384
  uint256 cleartext2 = _get(input2);
298
385
  if (cleartext2 == 0) {
299
386
  _set(ctHash, type(uint256).max);
@@ -302,143 +389,147 @@ abstract contract MockCoFHE {
302
389
  _set(ctHash, _get(input1) / cleartext2);
303
390
  }
304
391
  }
305
- logOperation('FHE.div', string.concat(logCtHash(input1), ' / ', logCtHash(input2)), logCtHash(ctHash));
392
+ if (logOps) logOperation('FHE.div', string.concat(logCtHash(input1), ' / ', logCtHash(input2)), logCtHash(ctHash));
306
393
  return;
307
394
  }
308
- if (opIs(operation, FunctionId.rem)) {
395
+ if (funcId == FunctionId.rem) {
309
396
  unchecked {
310
397
  _set(ctHash, _get(input1) % _get(input2));
311
398
  }
312
- logOperation('FHE.rem', string.concat(logCtHash(input1), ' % ', logCtHash(input2)), logCtHash(ctHash));
399
+ if (logOps) logOperation('FHE.rem', string.concat(logCtHash(input1), ' % ', logCtHash(input2)), logCtHash(ctHash));
313
400
  return;
314
401
  }
315
- if (opIs(operation, FunctionId.mul)) {
402
+ if (funcId == FunctionId.mul) {
316
403
  unchecked {
317
404
  _set(ctHash, _get(input1) * _get(input2));
318
405
  }
319
- logOperation('FHE.mul', string.concat(logCtHash(input1), ' * ', logCtHash(input2)), logCtHash(ctHash));
406
+ if (logOps) logOperation('FHE.mul', string.concat(logCtHash(input1), ' * ', logCtHash(input2)), logCtHash(ctHash));
320
407
  return;
321
408
  }
322
- if (opIs(operation, FunctionId.shl)) {
409
+ if (funcId == FunctionId.shl) {
323
410
  unchecked {
324
411
  _set(ctHash, _get(input1) << _get(input2));
325
412
  }
326
- logOperation('FHE.shl', string.concat(logCtHash(input1), ' << ', logCtHash(input2)), logCtHash(ctHash));
413
+ if (logOps) logOperation('FHE.shl', string.concat(logCtHash(input1), ' << ', logCtHash(input2)), logCtHash(ctHash));
327
414
  return;
328
415
  }
329
- if (opIs(operation, FunctionId.shr)) {
416
+ if (funcId == FunctionId.shr) {
330
417
  unchecked {
331
418
  _set(ctHash, _get(input1) >> _get(input2));
332
419
  }
333
- logOperation('FHE.shr', string.concat(logCtHash(input1), ' >> ', logCtHash(input2)), logCtHash(ctHash));
420
+ if (logOps) logOperation('FHE.shr', string.concat(logCtHash(input1), ' >> ', logCtHash(input2)), logCtHash(ctHash));
334
421
  return;
335
422
  }
336
- if (opIs(operation, FunctionId.gte)) {
423
+ if (funcId == FunctionId.gte) {
337
424
  _set(ctHash, _get(input1) >= _get(input2));
338
- logOperation('FHE.gte', string.concat(logCtHash(input1), ' >= ', logCtHash(input2)), logCtHash(ctHash));
425
+ if (logOps) logOperation('FHE.gte', string.concat(logCtHash(input1), ' >= ', logCtHash(input2)), logCtHash(ctHash));
339
426
  return;
340
427
  }
341
- if (opIs(operation, FunctionId.lte)) {
428
+ if (funcId == FunctionId.lte) {
342
429
  _set(ctHash, _get(input1) <= _get(input2));
343
- logOperation('FHE.lte', string.concat(logCtHash(input1), ' <= ', logCtHash(input2)), logCtHash(ctHash));
430
+ if (logOps) logOperation('FHE.lte', string.concat(logCtHash(input1), ' <= ', logCtHash(input2)), logCtHash(ctHash));
344
431
  return;
345
432
  }
346
- if (opIs(operation, FunctionId.lt)) {
433
+ if (funcId == FunctionId.lt) {
347
434
  _set(ctHash, _get(input1) < _get(input2));
348
- logOperation('FHE.lt', string.concat(logCtHash(input1), ' < ', logCtHash(input2)), logCtHash(ctHash));
435
+ if (logOps) logOperation('FHE.lt', string.concat(logCtHash(input1), ' < ', logCtHash(input2)), logCtHash(ctHash));
349
436
  return;
350
437
  }
351
- if (opIs(operation, FunctionId.gt)) {
438
+ if (funcId == FunctionId.gt) {
352
439
  _set(ctHash, _get(input1) > _get(input2));
353
- logOperation('FHE.gt', string.concat(logCtHash(input1), ' > ', logCtHash(input2)), logCtHash(ctHash));
440
+ if (logOps) logOperation('FHE.gt', string.concat(logCtHash(input1), ' > ', logCtHash(input2)), logCtHash(ctHash));
354
441
  return;
355
442
  }
356
- if (opIs(operation, FunctionId.min)) {
443
+ if (funcId == FunctionId.min) {
357
444
  uint256 min;
358
445
  unchecked {
359
446
  min = _get(input1) < _get(input2) ? _get(input1) : _get(input2);
360
447
  }
361
448
  _set(ctHash, min);
362
449
 
363
- logOperation(
364
- 'FHE.min',
365
- string.concat('min(', logCtHash(input1), ', ', logCtHash(input2), ')'),
366
- logCtHash(ctHash)
367
- );
450
+ if (logOps)
451
+ logOperation(
452
+ 'FHE.min',
453
+ string.concat('min(', logCtHash(input1), ', ', logCtHash(input2), ')'),
454
+ logCtHash(ctHash)
455
+ );
368
456
  return;
369
457
  }
370
- if (opIs(operation, FunctionId.max)) {
458
+ if (funcId == FunctionId.max) {
371
459
  uint256 max;
372
460
  unchecked {
373
461
  max = _get(input1) > _get(input2) ? _get(input1) : _get(input2);
374
462
  }
375
463
  _set(ctHash, max);
376
464
 
377
- logOperation(
378
- 'FHE.max',
379
- string.concat('max(', logCtHash(input1), ', ', logCtHash(input2), ')'),
380
- logCtHash(ctHash)
381
- );
465
+ if (logOps)
466
+ logOperation(
467
+ 'FHE.max',
468
+ string.concat('max(', logCtHash(input1), ', ', logCtHash(input2), ')'),
469
+ logCtHash(ctHash)
470
+ );
382
471
  return;
383
472
  }
384
- if (opIs(operation, FunctionId.eq)) {
473
+ if (funcId == FunctionId.eq) {
385
474
  _set(ctHash, _get(input1) == _get(input2));
386
475
 
387
- logOperation('FHE.eq', string.concat(logCtHash(input1), ' == ', logCtHash(input2)), logCtHash(ctHash));
476
+ if (logOps) logOperation('FHE.eq', string.concat(logCtHash(input1), ' == ', logCtHash(input2)), logCtHash(ctHash));
388
477
  return;
389
478
  }
390
- if (opIs(operation, FunctionId.ne)) {
479
+ if (funcId == FunctionId.ne) {
391
480
  _set(ctHash, _get(input1) != _get(input2));
392
481
 
393
- logOperation('FHE.ne', string.concat(logCtHash(input1), ' != ', logCtHash(input2)), logCtHash(ctHash));
482
+ if (logOps) logOperation('FHE.ne', string.concat(logCtHash(input1), ' != ', logCtHash(input2)), logCtHash(ctHash));
394
483
  return;
395
484
  }
396
- if (opIs(operation, FunctionId.rol)) {
485
+ if (funcId == FunctionId.rol) {
397
486
  unchecked {
398
487
  _set(ctHash, _get(input1) << _get(input2));
399
488
  }
400
489
 
401
- logOperation('FHE.rol', string.concat(logCtHash(input1), ' << ', logCtHash(input2)), logCtHash(ctHash));
490
+ if (logOps) logOperation('FHE.rol', string.concat(logCtHash(input1), ' << ', logCtHash(input2)), logCtHash(ctHash));
402
491
  return;
403
492
  }
404
- if (opIs(operation, FunctionId.ror)) {
493
+ if (funcId == FunctionId.ror) {
405
494
  unchecked {
406
495
  _set(ctHash, _get(input1) >> _get(input2));
407
496
  }
408
497
 
409
- logOperation('FHE.ror', string.concat(logCtHash(input1), ' >> ', logCtHash(input2)), logCtHash(ctHash));
498
+ if (logOps) logOperation('FHE.ror', string.concat(logCtHash(input1), ' >> ', logCtHash(input2)), logCtHash(ctHash));
410
499
  return;
411
500
  }
412
- revert InvalidTwoInputOperation(operation);
501
+ revert InvalidTwoInputOperation(Utils.functionIdToString(funcId));
413
502
  }
414
503
 
415
504
  function MOCK_threeInputOperation(
416
505
  uint256 ctHash,
417
- string memory operation,
506
+ FunctionId funcId,
418
507
  uint256 input1,
419
508
  uint256 input2,
420
509
  uint256 input3
421
510
  ) internal {
422
- if (opIs(operation, FunctionId.trivialEncrypt)) {
511
+ if (funcId == FunctionId.trivialEncrypt) {
423
512
  _set(ctHash, input1);
424
513
 
425
- logOperation(
426
- string.concat('FHE.asE', removeFirstLetter(getUtypeStringFromHash(ctHash))),
427
- string.concat(removeFirstLetter(getUtypeStringFromHash(ctHash)), '(', Strings.toString(input1), ')'),
428
- logCtHash(ctHash)
429
- );
514
+ if (logOps)
515
+ logOperation(
516
+ string.concat('FHE.asE', removeFirstLetter(getUtypeStringFromHash(ctHash))),
517
+ string.concat(removeFirstLetter(getUtypeStringFromHash(ctHash)), '(', Strings.toString(input1), ')'),
518
+ logCtHash(ctHash)
519
+ );
430
520
  return;
431
521
  }
432
- if (opIs(operation, FunctionId.select)) {
522
+ if (funcId == FunctionId.select) {
433
523
  _set(ctHash, _get(input1) == 1 ? _get(input2) : _get(input3));
434
524
 
435
- logOperation(
436
- 'FHE.select',
437
- string.concat(logCtHash(input1), ' ? ', logCtHash(input2), ' : ', logCtHash(input3)),
438
- logCtHash(ctHash)
439
- );
525
+ if (logOps)
526
+ logOperation(
527
+ 'FHE.select',
528
+ string.concat(logCtHash(input1), ' ? ', logCtHash(input2), ' : ', logCtHash(input3)),
529
+ logCtHash(ctHash)
530
+ );
440
531
  return;
441
532
  }
442
- revert InvalidThreeInputOperation(operation);
533
+ revert InvalidThreeInputOperation(Utils.functionIdToString(funcId));
443
534
  }
444
535
  }