@cofhe/mock-contracts 0.1.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.
@@ -0,0 +1,593 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause-Clear
2
+ /* solhint-disable one-contract-per-file */
3
+ pragma solidity >=0.8.25 <0.9.0;
4
+
5
+ import { MockACL, Permission } from './MockACL.sol';
6
+ // import {PlaintextsStorage} from "./PlaintextsStorage.sol";
7
+ import { Strings } from '@openzeppelin/contracts/utils/Strings.sol';
8
+ import { ECDSA } from '@openzeppelin/contracts/utils/cryptography/ECDSA.sol';
9
+ import { MockCoFHE } from './MockCoFHE.sol';
10
+ import { ITaskManager, FunctionId, Utils, EncryptedInput } from '@fhenixprotocol/cofhe-contracts/ICofhe.sol';
11
+
12
+ error DecryptionResultNotReady(uint256 ctHash);
13
+ // Input validation errors
14
+ error InvalidInputsAmount(string operation, uint256 got, uint256 expected);
15
+ error InvalidOperationInputs(string operation);
16
+ error TooManyInputs(string operation, uint256 got, uint256 maxAllowed);
17
+ error InvalidBytesLength(uint256 got, uint256 expected);
18
+ // Type and security validation errors
19
+ error InvalidTypeOrSecurityZone(string operation);
20
+ error InvalidInputType(uint8 actual, uint8 expected);
21
+ error InvalidInputForFunction(string functionName, uint8 inputType);
22
+ error InvalidSecurityZone(int32 zone, int32 min, int32 max);
23
+ error InvalidSignature();
24
+ error InvalidSigner(address signer, address expectedSigner);
25
+
26
+ // Access control errors
27
+ error InvalidAddress();
28
+ error OnlyOwnerAllowed(address caller);
29
+ error OnlyAggregatorAllowed(address caller);
30
+
31
+ // Operation-specific errors
32
+ error RandomFunctionNotSupported();
33
+
34
+ library TMCommon {
35
+ uint256 private constant HASH_MASK_FOR_METADATA = type(uint256).max - type(uint16).max; // 2 bytes reserved for metadata
36
+ uint256 private constant SECURITY_ZONE_MASK = type(uint8).max; // 0xff - 1 bytes reserved for security zone
37
+ uint256 private constant UINT_TYPE_MASK = (type(uint8).max >> 1); // 0x7f - 7 bits reserved for uint type in the one before last byte
38
+ uint256 private constant TRIVIALLY_ENCRYPTED_MASK = type(uint8).max - UINT_TYPE_MASK; //0x80 1 bit reserved for isTriviallyEncrypted
39
+ uint256 private constant SHIFTED_TYPE_MASK = UINT_TYPE_MASK << 8; // 0x7f007 bits reserved for uint type in the one before last byte
40
+
41
+ function uint256ToBytes32(uint256 value) internal pure returns (bytes memory) {
42
+ bytes memory result = new bytes(32);
43
+ assembly {
44
+ mstore(add(result, 32), value)
45
+ }
46
+ return result;
47
+ }
48
+
49
+ function combineInputs(
50
+ uint256[] memory encryptedHashes,
51
+ uint256[] memory extraInputs
52
+ ) internal pure returns (uint256[] memory) {
53
+ uint256[] memory inputs = new uint256[](encryptedHashes.length + extraInputs.length);
54
+ uint8 i = 0;
55
+ for (; i < encryptedHashes.length; i++) {
56
+ inputs[i] = encryptedHashes[i];
57
+ }
58
+ for (; i < encryptedHashes.length + extraInputs.length; i++) {
59
+ inputs[i] = extraInputs[i - encryptedHashes.length];
60
+ }
61
+
62
+ return inputs;
63
+ }
64
+
65
+ function getReturnType(FunctionId functionId, uint8 ctType) internal pure returns (uint8) {
66
+ if (
67
+ functionId == FunctionId.lte ||
68
+ functionId == FunctionId.lt ||
69
+ functionId == FunctionId.gte ||
70
+ functionId == FunctionId.gt ||
71
+ functionId == FunctionId.eq ||
72
+ functionId == FunctionId.ne
73
+ ) {
74
+ return Utils.EBOOL_TFHE;
75
+ }
76
+
77
+ return ctType;
78
+ }
79
+
80
+ /// @notice Calculates the temporary hash for async operations
81
+ /// @dev Must result the same temp hash as calculated by warp-drive/fhe-driver/CalcBinaryPlaceholderValueHash
82
+ /// @param functionId - The function id
83
+ /// @return The calculated temporary key
84
+ function calcPlaceholderKey(
85
+ uint8 ctType,
86
+ int32 securityZone,
87
+ uint256[] memory inputs,
88
+ FunctionId functionId
89
+ ) internal pure returns (uint256) {
90
+ bytes memory combined;
91
+ bool isTriviallyEncrypted = (functionId == FunctionId.trivialEncrypt);
92
+ for (uint8 i = 0; i < inputs.length; i++) {
93
+ combined = bytes.concat(combined, uint256ToBytes32(inputs[i]));
94
+ }
95
+
96
+ // Square is doing mul behind the scene
97
+ if (functionId == FunctionId.square) {
98
+ functionId = FunctionId.mul;
99
+ combined = bytes.concat(combined, uint256ToBytes32(inputs[0]));
100
+ }
101
+
102
+ bytes1 functionIdByte = bytes1(uint8(functionId));
103
+ combined = bytes.concat(combined, functionIdByte);
104
+
105
+ // Calculate Keccak256 hash
106
+ bytes32 hash = keccak256(combined);
107
+
108
+ // TODO: Trivially encrypted here isn't matching the check in `checkAllowed`
109
+ // - arcitect 2025-04-02
110
+
111
+ uint256 ctHash = appendMetadata(
112
+ uint256(hash),
113
+ securityZone,
114
+ getReturnType(functionId, ctType),
115
+ isTriviallyEncrypted
116
+ );
117
+
118
+ return ctHash;
119
+ }
120
+
121
+ function getByteForTrivialAndType(bool isTrivial, uint8 uintType) internal pure returns (uint256) {
122
+ /// @dev first bit for isTriviallyEncrypted
123
+ /// @dev last 7 bits for uintType
124
+
125
+ return uint256(((isTrivial ? TRIVIALLY_ENCRYPTED_MASK : 0x00) | (uintType & UINT_TYPE_MASK)));
126
+ }
127
+
128
+ /**
129
+ * Results format is: keccak256(operands_list, op)[0:29] || is_trivial (1 bit) & ct_type (7 bit) || securityZone || ct_version
130
+ */
131
+ function appendMetadata(
132
+ uint256 preCtHash,
133
+ int32 securityZone,
134
+ uint8 uintType,
135
+ bool isTrivial
136
+ ) internal pure returns (uint256 result) {
137
+ result = preCtHash & HASH_MASK_FOR_METADATA;
138
+ uint256 metadata = (getByteForTrivialAndType(isTrivial, uintType) << 8) | (uint256(uint8(int8(securityZone)))); /// @dev 8 bits for type, 8 bits for securityZone
139
+ result = result | metadata;
140
+ }
141
+
142
+ function getSecurityZoneFromHash(uint256 hash) internal pure returns (int32) {
143
+ return int32(int8(uint8(hash & SECURITY_ZONE_MASK)));
144
+ }
145
+
146
+ function getUintTypeFromHash(uint256 hash) internal pure returns (uint8) {
147
+ return uint8((hash & SHIFTED_TYPE_MASK) >> 8);
148
+ }
149
+
150
+ function getSecAndTypeFromHash(uint256 hash) internal pure returns (uint256) {
151
+ return uint256((SHIFTED_TYPE_MASK | SECURITY_ZONE_MASK) & hash);
152
+ }
153
+ function isTriviallyEncryptedFromHash(uint256 hash) internal pure returns (bool) {
154
+ return (hash & TRIVIALLY_ENCRYPTED_MASK) == TRIVIALLY_ENCRYPTED_MASK;
155
+ }
156
+ }
157
+
158
+ contract MockTaskManager is ITaskManager, MockCoFHE {
159
+ address owner;
160
+ bool private initialized;
161
+
162
+ // NOTE: MOCK PLAINTEXTS STORAGE
163
+ mapping(uint256 ctHash => uint256) private _decryptResult;
164
+ mapping(uint256 ctHash => bool) private _decryptResultReady;
165
+ mapping(uint256 ctHash => uint64) private _decryptResultReadyTimestamp;
166
+
167
+ /// @custom:oz-upgrades-unsafe-allow constructor
168
+ constructor() {}
169
+
170
+ /**
171
+ * @notice Initializes the contract.
172
+ * @param initialOwner Initial owner address.
173
+ */
174
+ function initialize(address initialOwner) public {
175
+ owner = initialOwner;
176
+ initialized = true;
177
+ verifierSigner = address(0);
178
+ }
179
+
180
+ modifier onlyOwner() {
181
+ if (msg.sender != owner) revert OnlyOwnerAllowed(msg.sender);
182
+ _;
183
+ }
184
+
185
+ function setSecurityZones(int32 minSZ, int32 maxSZ) external onlyOwner {
186
+ securityZoneMin = minSZ;
187
+ securityZoneMax = maxSZ;
188
+ }
189
+
190
+ function isInitialized() public view returns (bool) {
191
+ return initialized;
192
+ }
193
+
194
+ // Errors
195
+ // Returned when the handle is not allowed in the ACL for the account.
196
+ error ACLNotAllowed(uint256 handle, address account);
197
+
198
+ // Events
199
+ event TaskCreated(uint256 ctHash, string operation, uint256 input1, uint256 input2, uint256 input3);
200
+ event ProtocolNotification(uint256 ctHash, string operation, string errorMessage);
201
+ event DecryptionResult(uint256 ctHash, uint256 result, address indexed requestor);
202
+
203
+ struct Task {
204
+ address creator;
205
+ uint256 createdAt;
206
+ bool isResultReady;
207
+ }
208
+
209
+ // Supported Security Zones
210
+ int32 private securityZoneMax;
211
+ int32 private securityZoneMin;
212
+
213
+ // Address of the aggregator
214
+ address public aggregator;
215
+
216
+ // Access-Control contract
217
+ MockACL public acl;
218
+
219
+ address private verifierSigner;
220
+
221
+ // Storage contract for plaintext results of decrypt operations
222
+ // PlaintextsStorage public plaintextsStorage;
223
+
224
+ modifier onlyAggregator() {
225
+ if (msg.sender != aggregator) {
226
+ revert OnlyAggregatorAllowed(msg.sender);
227
+ }
228
+ _;
229
+ }
230
+
231
+ function exists() public pure returns (bool) {
232
+ return true;
233
+ }
234
+
235
+ function sendEventCreated(uint256 ctHash, string memory operation, uint256[] memory inputs) private {
236
+ if (inputs.length == 1 || opIs(operation, FunctionId.cast)) {
237
+ emit TaskCreated(ctHash, operation, inputs[0], 0, 0);
238
+
239
+ // NOTE: MOCK
240
+ MOCK_unaryOperation(ctHash, operation, inputs[0]);
241
+ } else if (inputs.length == 2) {
242
+ emit TaskCreated(ctHash, operation, inputs[0], inputs[1], 0);
243
+
244
+ // NOTE: MOCK
245
+ MOCK_twoInputOperation(ctHash, operation, inputs[0], inputs[1]);
246
+ } else {
247
+ emit TaskCreated(ctHash, operation, inputs[0], inputs[1], inputs[2]);
248
+
249
+ // NOTE: MOCK
250
+ MOCK_threeInputOperation(ctHash, operation, inputs[0], inputs[1], inputs[2]);
251
+ }
252
+ }
253
+
254
+ function createDecryptTask(uint256 ctHash, address /*requestor*/) public {
255
+ checkAllowed(ctHash);
256
+
257
+ // NOTE: MOCK COMMENTED
258
+ // (uint256 result, bool hasResult) = plaintextsStorage.getResult(ctHash);
259
+ // if (hasResult) {
260
+ // emit DecryptionResult(ctHash, result, requestor);
261
+ // } else {
262
+ // uint256[] memory inputs = new uint256[](1);
263
+ // inputs[0] = uint256(uint160(requestor));
264
+ // sendEventCreated(
265
+ // ctHash,
266
+ // Utils.functionIdToString(FunctionId.decrypt),
267
+ // inputs
268
+ // );
269
+ // }
270
+
271
+ // NOTE: MOCK
272
+ _decryptResultReady[ctHash] = true;
273
+ _decryptResult[ctHash] = _get(ctHash);
274
+
275
+ uint64 asyncOffset = uint64((block.timestamp % 10) + 1);
276
+ _decryptResultReadyTimestamp[ctHash] = uint64(block.timestamp) + asyncOffset;
277
+ }
278
+
279
+ function getDecryptResult(uint256 ctHash) public view returns (uint256) {
280
+ (uint256 result, bool decrypted) = getDecryptResultSafe(ctHash);
281
+ if (!decrypted) revert DecryptionResultNotReady(ctHash);
282
+ return result;
283
+ }
284
+
285
+ function getDecryptResultSafe(uint256 ctHash) public view returns (uint256 result, bool decrypted) {
286
+ if (!_decryptResultReady[ctHash]) return (0, false);
287
+
288
+ // NOTE: MOCK
289
+ if (block.timestamp < _decryptResultReadyTimestamp[ctHash]) return (0, false);
290
+
291
+ return (_get(ctHash), true);
292
+ }
293
+
294
+ function checkAllowed(uint256 ctHash) internal view {
295
+ if (!TMCommon.isTriviallyEncryptedFromHash(ctHash)) {
296
+ if (!acl.isAllowed(ctHash, msg.sender)) revert ACLNotAllowed(ctHash, msg.sender);
297
+ }
298
+ }
299
+
300
+ function isUnaryOperation(FunctionId funcId) internal pure returns (bool) {
301
+ return funcId == FunctionId.not || funcId == FunctionId.square || funcId == FunctionId.cast;
302
+ }
303
+
304
+ function isPlaintextOperation(FunctionId funcId) internal pure returns (bool) {
305
+ return funcId == FunctionId.random || funcId == FunctionId.trivialEncrypt;
306
+ }
307
+
308
+ function getSecurityZone(
309
+ FunctionId functionId,
310
+ uint256[] memory encryptedInputs,
311
+ uint256[] memory plaintextInputs
312
+ ) internal pure returns (int32) {
313
+ if (isPlaintextOperation(functionId)) {
314
+ // If inputs are plaintext (currently trivialEncrypt and random) the security zone will be the last input
315
+ return int32(int256(plaintextInputs[plaintextInputs.length - 1]));
316
+ }
317
+
318
+ // First param of a function that receives some encrypted values will always be encrypted
319
+ // Refer to: combineInput for more details
320
+ return TMCommon.getSecurityZoneFromHash(encryptedInputs[0]);
321
+ }
322
+
323
+ function isValidSecurityZone(int32 _securityZone) internal view returns (bool) {
324
+ return _securityZone >= securityZoneMin && _securityZone <= securityZoneMax;
325
+ }
326
+
327
+ function validateEncryptedHashes(uint256[] memory encryptedHashes) internal view {
328
+ for (uint8 i = 0; i < encryptedHashes.length; i++) {
329
+ checkAllowed(encryptedHashes[i]);
330
+ }
331
+ }
332
+
333
+ // Verifies if a function is a function that supports all types (including select for ifTrue, ifFalse)
334
+ function isAllTypesFunction(FunctionId funcId) internal pure returns (bool) {
335
+ return
336
+ funcId == FunctionId.select || funcId == FunctionId.eq || funcId == FunctionId.ne || funcId == FunctionId.cast;
337
+ }
338
+
339
+ // Verifies if a function is receives ONLY boolean or numeral inputs
340
+ function isBooleanAndNumeralFunction(FunctionId funcId) internal pure returns (bool) {
341
+ return funcId == FunctionId.xor || funcId == FunctionId.and || funcId == FunctionId.or || funcId == FunctionId.not;
342
+ }
343
+
344
+ function validateFunctionInputTypes(
345
+ FunctionId funcId,
346
+ string memory functionName,
347
+ uint256[] memory inputs
348
+ ) internal pure {
349
+ if (isAllTypesFunction(funcId)) {
350
+ return;
351
+ }
352
+
353
+ if (isBooleanAndNumeralFunction(funcId)) {
354
+ for (uint8 i = 0; i < inputs.length; i++) {
355
+ uint8 inputType = TMCommon.getUintTypeFromHash(inputs[i]);
356
+ if ((inputType ^ Utils.EADDRESS_TFHE) == 0) {
357
+ revert InvalidInputForFunction(functionName, Utils.EADDRESS_TFHE);
358
+ }
359
+ }
360
+ } else {
361
+ // In this case we expect a function that only work with numbers
362
+ for (uint8 i = 0; i < inputs.length; i++) {
363
+ uint8 inputType = TMCommon.getUintTypeFromHash(inputs[i]);
364
+ if ((inputType ^ Utils.EADDRESS_TFHE) == 0 || (inputType ^ Utils.EBOOL_TFHE) == 0) {
365
+ revert InvalidInputForFunction(functionName, inputType);
366
+ }
367
+ }
368
+ }
369
+ }
370
+
371
+ function validateInputs(uint256[] memory encryptedHashes, FunctionId funcId) internal view {
372
+ string memory functionName = Utils.functionIdToString(funcId);
373
+
374
+ if (encryptedHashes.length == 0) {
375
+ if (!isPlaintextOperation(funcId)) {
376
+ revert InvalidOperationInputs(functionName);
377
+ }
378
+ return;
379
+ }
380
+
381
+ if (funcId == FunctionId.select) {
382
+ validateSelectInputs(encryptedHashes);
383
+ } else if (isUnaryOperation(funcId)) {
384
+ if (encryptedHashes.length != 1) {
385
+ revert InvalidInputsAmount(functionName, encryptedHashes.length, 1);
386
+ }
387
+ } else {
388
+ if (encryptedHashes.length != 2) {
389
+ revert InvalidInputsAmount(functionName, encryptedHashes.length, 2);
390
+ }
391
+ if ((TMCommon.getSecAndTypeFromHash(encryptedHashes[0] ^ encryptedHashes[1])) != 0) {
392
+ revert InvalidTypeOrSecurityZone(functionName);
393
+ }
394
+ }
395
+
396
+ int32 securityZone = TMCommon.getSecurityZoneFromHash(encryptedHashes[0]);
397
+ if (!isValidSecurityZone(securityZone)) {
398
+ revert InvalidSecurityZone(securityZone, securityZoneMin, securityZoneMax);
399
+ }
400
+ validateEncryptedHashes(encryptedHashes);
401
+ validateFunctionInputTypes(funcId, functionName, encryptedHashes);
402
+ }
403
+
404
+ function validateSelectInputs(uint256[] memory encryptedHashes) internal pure {
405
+ if (encryptedHashes.length != 3) {
406
+ revert InvalidInputsAmount('select', encryptedHashes.length, 3);
407
+ }
408
+ if ((TMCommon.getSecAndTypeFromHash(encryptedHashes[1] ^ encryptedHashes[2])) != 0) {
409
+ revert InvalidTypeOrSecurityZone('select');
410
+ }
411
+
412
+ uint8 uintType = TMCommon.getUintTypeFromHash(encryptedHashes[0]);
413
+ if ((uintType ^ Utils.EBOOL_TFHE) != 0) {
414
+ revert InvalidInputType(uintType, Utils.EBOOL_TFHE);
415
+ }
416
+ }
417
+
418
+ function createTask(
419
+ uint8 returnType,
420
+ FunctionId funcId,
421
+ uint256[] memory encryptedHashes,
422
+ uint256[] memory extraInputs
423
+ ) external returns (uint256) {
424
+ if (funcId == FunctionId.random) {
425
+ revert RandomFunctionNotSupported();
426
+ }
427
+ uint256 inputsLength = encryptedHashes.length + extraInputs.length;
428
+ if (inputsLength > 3) {
429
+ revert TooManyInputs(Utils.functionIdToString(funcId), inputsLength, 3);
430
+ }
431
+
432
+ validateInputs(encryptedHashes, funcId);
433
+ uint256[] memory inputs = TMCommon.combineInputs(encryptedHashes, extraInputs);
434
+
435
+ int32 securityZone = getSecurityZone(funcId, encryptedHashes, extraInputs);
436
+ uint256 ctHash = TMCommon.calcPlaceholderKey(returnType, securityZone, inputs, funcId);
437
+
438
+ acl.allowTransient(ctHash, msg.sender, address(this));
439
+ sendEventCreated(ctHash, Utils.functionIdToString(funcId), inputs);
440
+
441
+ return ctHash;
442
+ }
443
+
444
+ function handleDecryptResult(
445
+ uint256 ctHash,
446
+ uint256 result,
447
+ address[] calldata /*requestors*/
448
+ ) external onlyAggregator {
449
+ // plaintextsStorage.storeResult(ctHash, result);
450
+ // for (uint8 i = 0; i < requestors.length; i++) {
451
+ // emit DecryptionResult(ctHash, result, requestors[i]);
452
+ // }
453
+
454
+ _decryptResultReady[ctHash] = true;
455
+ _decryptResult[ctHash] = result;
456
+ _decryptResultReadyTimestamp[ctHash] = uint64(block.timestamp);
457
+ }
458
+
459
+ function handleError(uint256 ctHash, string memory operation, string memory errorMessage) external onlyAggregator {
460
+ emit ProtocolNotification(ctHash, operation, errorMessage);
461
+ }
462
+
463
+ function verifyType(uint8 ctType, uint8 desiredType) internal pure {
464
+ if (ctType != desiredType) {
465
+ revert InvalidInputType(ctType, desiredType);
466
+ }
467
+ }
468
+
469
+ function verifyInput(EncryptedInput memory input, address sender) external returns (uint256) {
470
+ int32 securityZone = int32(uint32(input.securityZone));
471
+
472
+ // When signer is set to 0 address we skip this logic to be able to support debug use cases.
473
+ // In debug use cases we assume that the verifier is not necessarily running.
474
+ if (verifierSigner != address(0)) {
475
+ if (!isValidSecurityZone(securityZone)) {
476
+ revert InvalidSecurityZone(securityZone, securityZoneMin, securityZoneMax);
477
+ }
478
+
479
+ address signer = extractSigner(input, sender);
480
+ if (signer != verifierSigner) {
481
+ revert InvalidSigner(signer, verifierSigner);
482
+ }
483
+ }
484
+
485
+ uint256 appendedHash = TMCommon.appendMetadata(input.ctHash, securityZone, input.utype, false);
486
+
487
+ acl.allowTransient(appendedHash, msg.sender, address(this));
488
+ return appendedHash;
489
+ }
490
+
491
+ function allow(uint256 ctHash, address account) external {
492
+ if (!TMCommon.isTriviallyEncryptedFromHash(ctHash)) {
493
+ acl.allow(ctHash, account, msg.sender);
494
+
495
+ // NOTE: MOCK
496
+ MOCK_logAllow(account == msg.sender ? 'FHE.allowThis' : 'FHE.allow', ctHash, account);
497
+ }
498
+ }
499
+
500
+ function allowGlobal(uint256 ctHash) external {
501
+ if (!TMCommon.isTriviallyEncryptedFromHash(ctHash)) {
502
+ acl.allowGlobal(ctHash, msg.sender);
503
+
504
+ // NOTE: MOCK
505
+ MOCK_logAllow('FHE.allowGlobal', ctHash, msg.sender);
506
+ }
507
+ }
508
+
509
+ function allowTransient(uint256 ctHash, address account) external {
510
+ if (!TMCommon.isTriviallyEncryptedFromHash(ctHash)) {
511
+ acl.allowTransient(ctHash, account, msg.sender);
512
+
513
+ // NOTE: MOCK
514
+ MOCK_logAllow('FHE.allowTransient', ctHash, account);
515
+ }
516
+ }
517
+
518
+ function allowForDecryption(uint256 ctHash) external {
519
+ if (!TMCommon.isTriviallyEncryptedFromHash(ctHash)) {
520
+ uint256[] memory hashes = new uint256[](1);
521
+ hashes[0] = ctHash;
522
+ acl.allowForDecryption(hashes, msg.sender);
523
+
524
+ // NOTE: MOCK
525
+ MOCK_logAllow('FHE.allowForDecryption', ctHash, msg.sender);
526
+ }
527
+ }
528
+
529
+ function isAllowed(uint256 ctHash, address account) external view returns (bool) {
530
+ if (TMCommon.isTriviallyEncryptedFromHash(ctHash)) {
531
+ return true;
532
+ }
533
+ return acl.isAllowed(ctHash, account);
534
+ }
535
+
536
+ function extractSigner(EncryptedInput memory input, address sender) private view returns (address) {
537
+ bytes memory combined = abi.encodePacked(input.ctHash, input.utype, input.securityZone, sender, block.chainid);
538
+
539
+ bytes32 expectedHash = keccak256(combined);
540
+
541
+ address signer = ECDSA.recover(expectedHash, input.signature);
542
+ if (signer == address(0)) {
543
+ revert InvalidSignature();
544
+ }
545
+
546
+ return signer;
547
+ }
548
+
549
+ function setVerifierSigner(address signer) external onlyOwner {
550
+ verifierSigner = signer;
551
+ }
552
+
553
+ function setSecurityZoneMax(int32 securityZone) external onlyOwner {
554
+ if (securityZone < securityZoneMin) {
555
+ revert InvalidSecurityZone(securityZone, securityZoneMin, securityZoneMax);
556
+ }
557
+ securityZoneMax = securityZone;
558
+ }
559
+
560
+ function setSecurityZoneMin(int32 securityZone) external onlyOwner {
561
+ if (securityZone > securityZoneMax) {
562
+ revert InvalidSecurityZone(securityZone, securityZoneMin, securityZoneMax);
563
+ }
564
+ securityZoneMin = securityZone;
565
+ }
566
+
567
+ function setACLContract(address _aclAddress) external onlyOwner {
568
+ if (_aclAddress == address(0)) {
569
+ revert InvalidAddress();
570
+ }
571
+ acl = MockACL(_aclAddress);
572
+ }
573
+
574
+ // function setPlaintextsStorage(
575
+ // address _plaintextsStorageAddress
576
+ // ) external onlyOwner {
577
+ // if (_plaintextsStorageAddress == address(0)) {
578
+ // revert InvalidAddress();
579
+ // }
580
+ // plaintextsStorage = PlaintextsStorage(_plaintextsStorageAddress);
581
+ // }
582
+
583
+ function setAggregator(address _aggregatorAddress) external onlyOwner {
584
+ if (_aggregatorAddress == address(0)) {
585
+ revert InvalidAddress();
586
+ }
587
+ aggregator = _aggregatorAddress;
588
+ }
589
+
590
+ function isAllowedWithPermission(Permission memory permission, uint256 handle) public view returns (bool) {
591
+ return acl.isAllowedWithPermission(permission, handle);
592
+ }
593
+ }