@cofhe/mock-contracts 0.8.0 → 1.0.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 +37 -0
- package/contracts/ACPShareRegistry.sol +227 -114
- package/contracts/ACPTimestampRevoker.sol +36 -34
- package/contracts/MockACL.sol +2 -1
- package/contracts/MockCoFHE.sol +36 -12
- package/contracts/MockERC1967Proxy.sol +13 -0
- package/contracts/MockPermissioned.sol +16 -0
- package/contracts/MockTaskManager.sol +124 -60
- package/contracts/MockThresholdNetwork.sol +5 -5
- package/contracts/Permissioned.sol +240 -143
- package/contracts/cofhe-contracts.json +10 -0
- package/dist/index.d.mts +689 -77
- package/dist/index.d.ts +689 -77
- package/dist/index.js +576 -82
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +576 -83
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -5
- package/remappings.txt +1 -0
- package/src/ACPShareRegistry.ts +469 -56
- package/src/MockACL.ts +19 -12
- package/src/MockERC1967Proxy.ts +74 -0
- package/src/MockTaskManager.ts +1 -1
- package/src/index.ts +2 -0
- package/src/typechain-types/ACPShareRegistry.ts +309 -12
- package/src/typechain-types/MockACL.ts +27 -0
- package/src/typechain-types/MockERC1967Proxy.ts +85 -0
- package/src/typechain-types/index.ts +1 -0
|
@@ -16,6 +16,7 @@ error InvalidInputsAmount(string operation, uint256 got, uint256 expected);
|
|
|
16
16
|
error InvalidOperationInputs(string operation);
|
|
17
17
|
error TooManyInputs(string operation, uint256 got, uint256 maxAllowed);
|
|
18
18
|
error InvalidBytesLength(uint256 got, uint256 expected);
|
|
19
|
+
error LengthMismatch();
|
|
19
20
|
// Type and security validation errors
|
|
20
21
|
error InvalidTypeOrSecurityZone(string operation);
|
|
21
22
|
error InvalidInputType(uint8 actual, uint8 expected);
|
|
@@ -31,7 +32,6 @@ error OnlyAggregatorAllowed(address caller);
|
|
|
31
32
|
|
|
32
33
|
// Operation-specific errors
|
|
33
34
|
error RandomFunctionNotSupported();
|
|
34
|
-
error NotImplemented();
|
|
35
35
|
|
|
36
36
|
library TMCommon {
|
|
37
37
|
uint256 private constant HASH_MASK_FOR_METADATA = type(uint256).max - type(uint16).max; // 2 bytes reserved for metadata
|
|
@@ -159,10 +159,6 @@ library TMCommon {
|
|
|
159
159
|
return uint256((SHIFTED_TYPE_MASK | SECURITY_ZONE_MASK) & hash);
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
function isTriviallyEncryptedFromHash(uint256 hash) internal pure returns (bool) {
|
|
163
|
-
return (hash & TRIVIALLY_ENCRYPTED_MASK) == TRIVIALLY_ENCRYPTED_MASK;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
162
|
function computeDecryptResultHash(
|
|
167
163
|
uint256 ctHash,
|
|
168
164
|
uint256 result,
|
|
@@ -211,8 +207,17 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
211
207
|
}
|
|
212
208
|
|
|
213
209
|
function setSecurityZones(int32 minSZ, int32 maxSZ) external onlyOwner {
|
|
214
|
-
|
|
215
|
-
|
|
210
|
+
_setSecurityZones(minSZ, maxSZ);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/// @dev Same check as the real task manager's `_setSecurityZones`, the one write path for the bounds.
|
|
214
|
+
/// Without it `setSecurityZones(2, 1)` would be stored here while the real task manager reverts.
|
|
215
|
+
function _setSecurityZones(int32 newMin, int32 newMax) private {
|
|
216
|
+
if (newMin > newMax) {
|
|
217
|
+
revert InvalidSecurityZone(newMin, newMin, newMax);
|
|
218
|
+
}
|
|
219
|
+
securityZoneMin = newMin;
|
|
220
|
+
securityZoneMax = newMax;
|
|
216
221
|
}
|
|
217
222
|
|
|
218
223
|
function isInitialized() public view returns (bool) {
|
|
@@ -249,6 +254,9 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
249
254
|
// Signer address for decrypt result verification (threshold network's signing key)
|
|
250
255
|
address public decryptResultSigner;
|
|
251
256
|
|
|
257
|
+
// Counter mixed into generated random seeds, as in the real task manager
|
|
258
|
+
uint256 private randomCounter;
|
|
259
|
+
|
|
252
260
|
// Storage contract for plaintext results of decrypt operations
|
|
253
261
|
// PlaintextsStorage public plaintextsStorage;
|
|
254
262
|
|
|
@@ -370,9 +378,7 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
370
378
|
}
|
|
371
379
|
|
|
372
380
|
function checkAllowed(uint256 ctHash) internal view {
|
|
373
|
-
if (!
|
|
374
|
-
if (!acl.isAllowed(ctHash, msg.sender)) revert ACLNotAllowed(ctHash, msg.sender);
|
|
375
|
-
}
|
|
381
|
+
if (!acl.isAllowed(ctHash, msg.sender)) revert ACLNotAllowed(ctHash, msg.sender);
|
|
376
382
|
}
|
|
377
383
|
|
|
378
384
|
function isUnaryOperation(FunctionId funcId) internal pure returns (bool) {
|
|
@@ -481,6 +487,32 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
481
487
|
validateFunctionInputTypes(funcId, functionName, encryptedHashes);
|
|
482
488
|
}
|
|
483
489
|
|
|
490
|
+
/// @dev Same checks as the real task manager: the plaintext must fit the target type and the
|
|
491
|
+
/// security zone must be in range. Without them `FHE.asEuint8(256)` would be stored masked
|
|
492
|
+
/// to 0 here while the real task manager reverts.
|
|
493
|
+
function validateTrivialEncryptInputs(uint256[] memory extraInputs) internal view {
|
|
494
|
+
uint256 securityZone = extraInputs[2];
|
|
495
|
+
if (securityZone > uint256(int256(type(int32).max)) || !isValidSecurityZone(int32(int256(securityZone)))) {
|
|
496
|
+
revert InvalidSecurityZone(int32(int256(securityZone)), securityZoneMin, securityZoneMax);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
uint256 value = extraInputs[0];
|
|
500
|
+
uint256 toType = extraInputs[1];
|
|
501
|
+
uint256 max;
|
|
502
|
+
if (toType == Utils.EUINT8_TFHE) max = type(uint8).max;
|
|
503
|
+
else if (toType == Utils.EUINT16_TFHE) max = type(uint16).max;
|
|
504
|
+
else if (toType == Utils.EUINT32_TFHE) max = type(uint32).max;
|
|
505
|
+
else if (toType == Utils.EUINT64_TFHE) max = type(uint64).max;
|
|
506
|
+
else if (toType == Utils.EUINT128_TFHE) max = type(uint128).max;
|
|
507
|
+
else if (toType == Utils.EADDRESS_TFHE) max = type(uint160).max;
|
|
508
|
+
else if (toType == Utils.EBOOL_TFHE) max = 1;
|
|
509
|
+
else return;
|
|
510
|
+
|
|
511
|
+
if (value > max) {
|
|
512
|
+
revert InvalidInputForFunction('trivialEncrypt', uint8(toType));
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
484
516
|
function validateSelectInputs(uint256[] memory encryptedHashes) internal pure {
|
|
485
517
|
if (encryptedHashes.length != 3) {
|
|
486
518
|
revert InvalidInputsAmount('select', encryptedHashes.length, 3);
|
|
@@ -511,6 +543,9 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
511
543
|
}
|
|
512
544
|
|
|
513
545
|
validateInputs(encryptedHashes, funcId, operation);
|
|
546
|
+
if (funcId == FunctionId.trivialEncrypt) {
|
|
547
|
+
validateTrivialEncryptInputs(extraInputs);
|
|
548
|
+
}
|
|
514
549
|
uint256[] memory inputs = TMCommon.combineInputs(encryptedHashes, extraInputs);
|
|
515
550
|
|
|
516
551
|
int32 securityZone = getSecurityZone(funcId, encryptedHashes, extraInputs);
|
|
@@ -544,12 +579,7 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
544
579
|
/// @notice Publish a signed decrypt result to the chain
|
|
545
580
|
/// @dev Anyone with a valid signature from the decrypt network can call this
|
|
546
581
|
function publishDecryptResult(uint256 ctHash, uint256 result, bytes calldata signature) external {
|
|
547
|
-
|
|
548
|
-
_decryptResultReady[ctHash] = true;
|
|
549
|
-
_decryptResult[ctHash] = result;
|
|
550
|
-
|
|
551
|
-
_decryptResultReadyTimestamp[ctHash] = uint64(block.timestamp);
|
|
552
|
-
emit DecryptionResult(ctHash, result, msg.sender);
|
|
582
|
+
_publishDecryptResult(ctHash, result, signature);
|
|
553
583
|
}
|
|
554
584
|
|
|
555
585
|
function publishDecryptResultBatch(
|
|
@@ -557,14 +587,25 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
557
587
|
uint256[] calldata results,
|
|
558
588
|
bytes[] calldata signatures
|
|
559
589
|
) external {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
590
|
+
uint256 length = ctHashes.length;
|
|
591
|
+
if (results.length != length || signatures.length != length) revert LengthMismatch();
|
|
592
|
+
|
|
593
|
+
for (uint256 i = 0; i < length; i++) {
|
|
594
|
+
_publishDecryptResult(ctHashes[i], results[i], signatures[i]);
|
|
565
595
|
}
|
|
566
596
|
}
|
|
567
597
|
|
|
598
|
+
/// @dev Shared by both publish functions, so a batch keeps its caller as the `DecryptionResult` requestor,
|
|
599
|
+
/// like the real task manager. An external self-call would make the requestor this contract.
|
|
600
|
+
function _publishDecryptResult(uint256 ctHash, uint256 result, bytes calldata signature) private {
|
|
601
|
+
_verifyDecryptResult(ctHash, result, signature, true);
|
|
602
|
+
_decryptResultReady[ctHash] = true;
|
|
603
|
+
_decryptResult[ctHash] = result;
|
|
604
|
+
|
|
605
|
+
_decryptResultReadyTimestamp[ctHash] = uint64(block.timestamp);
|
|
606
|
+
emit DecryptionResult(ctHash, result, msg.sender);
|
|
607
|
+
}
|
|
608
|
+
|
|
568
609
|
function verifyDecryptResult(uint256 ctHash, uint256 result, bytes calldata signature) external view returns (bool) {
|
|
569
610
|
return _verifyDecryptResult(ctHash, result, signature, true);
|
|
570
611
|
}
|
|
@@ -657,47 +698,36 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
657
698
|
}
|
|
658
699
|
|
|
659
700
|
function allow(uint256 ctHash, address account) external {
|
|
660
|
-
|
|
661
|
-
acl.allow(ctHash, account, msg.sender);
|
|
701
|
+
acl.allow(ctHash, account, msg.sender);
|
|
662
702
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
}
|
|
703
|
+
// NOTE: MOCK
|
|
704
|
+
MOCK_trackedLogAllow(account == msg.sender ? 'FHE.allowThis' : 'FHE.allow', ctHash, account);
|
|
666
705
|
}
|
|
667
706
|
|
|
668
707
|
function allowGlobal(uint256 ctHash) external {
|
|
669
|
-
|
|
670
|
-
acl.allowGlobal(ctHash, msg.sender);
|
|
708
|
+
acl.allowGlobal(ctHash, msg.sender);
|
|
671
709
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
}
|
|
710
|
+
// NOTE: MOCK
|
|
711
|
+
MOCK_trackedLogAllow('FHE.allowGlobal', ctHash, msg.sender);
|
|
675
712
|
}
|
|
676
713
|
|
|
677
714
|
function allowTransient(uint256 ctHash, address account) external {
|
|
678
|
-
|
|
679
|
-
acl.allowTransient(ctHash, account, msg.sender);
|
|
715
|
+
acl.allowTransient(ctHash, account, msg.sender);
|
|
680
716
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
}
|
|
717
|
+
// NOTE: MOCK
|
|
718
|
+
MOCK_trackedLogAllow('FHE.allowTransient', ctHash, account);
|
|
684
719
|
}
|
|
685
720
|
|
|
686
721
|
function allowForDecryption(uint256 ctHash) external {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
acl.allowForDecryption(hashes, msg.sender);
|
|
722
|
+
uint256[] memory hashes = new uint256[](1);
|
|
723
|
+
hashes[0] = ctHash;
|
|
724
|
+
acl.allowForDecryption(hashes, msg.sender);
|
|
691
725
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
}
|
|
726
|
+
// NOTE: MOCK
|
|
727
|
+
MOCK_trackedLogAllow('FHE.allowForDecryption', ctHash, msg.sender);
|
|
695
728
|
}
|
|
696
729
|
|
|
697
730
|
function isAllowed(uint256 ctHash, address account) external view returns (bool) {
|
|
698
|
-
if (TMCommon.isTriviallyEncryptedFromHash(ctHash)) {
|
|
699
|
-
return true;
|
|
700
|
-
}
|
|
701
731
|
return acl.isAllowed(ctHash, account);
|
|
702
732
|
}
|
|
703
733
|
|
|
@@ -769,17 +799,11 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
769
799
|
}
|
|
770
800
|
|
|
771
801
|
function setSecurityZoneMax(int32 securityZone) external onlyOwner {
|
|
772
|
-
|
|
773
|
-
revert InvalidSecurityZone(securityZone, securityZoneMin, securityZoneMax);
|
|
774
|
-
}
|
|
775
|
-
securityZoneMax = securityZone;
|
|
802
|
+
_setSecurityZones(securityZoneMin, securityZone);
|
|
776
803
|
}
|
|
777
804
|
|
|
778
805
|
function setSecurityZoneMin(int32 securityZone) external onlyOwner {
|
|
779
|
-
|
|
780
|
-
revert InvalidSecurityZone(securityZone, securityZoneMin, securityZoneMax);
|
|
781
|
-
}
|
|
782
|
-
securityZoneMin = securityZone;
|
|
806
|
+
_setSecurityZones(securityZone, securityZoneMax);
|
|
783
807
|
}
|
|
784
808
|
|
|
785
809
|
function setACLContract(address _aclAddress) external onlyOwner {
|
|
@@ -813,12 +837,46 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
813
837
|
// Stub implementations for new ITaskManager interface methods (inc PR #48)
|
|
814
838
|
|
|
815
839
|
function createRandomTask(uint8 returnType, uint256 seed, int32 securityZone) external returns (uint256) {
|
|
816
|
-
|
|
817
|
-
|
|
840
|
+
if (!isValidSecurityZone(securityZone)) {
|
|
841
|
+
revert InvalidSecurityZone(securityZone, securityZoneMin, securityZoneMax);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
if (seed == 0) {
|
|
845
|
+
seed = uint256(
|
|
846
|
+
keccak256(
|
|
847
|
+
abi.encodePacked(blockhash(block.number - 1), block.timestamp, randomCounter, block.chainid, securityZone)
|
|
848
|
+
)
|
|
849
|
+
);
|
|
850
|
+
unchecked {
|
|
851
|
+
randomCounter++;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// Same handle derivation as the real task manager: msg.sender is part of the preimage.
|
|
856
|
+
uint256[] memory inputs = new uint256[](2);
|
|
857
|
+
inputs[0] = seed;
|
|
858
|
+
inputs[1] = uint256(uint160(msg.sender));
|
|
859
|
+
|
|
860
|
+
uint256 ctHash = TMCommon.calcPlaceholderKey(returnType, securityZone, inputs, FunctionId.random);
|
|
861
|
+
acl.allowTransient(ctHash, msg.sender, address(this));
|
|
862
|
+
emit TaskCreated(
|
|
863
|
+
ctHash,
|
|
864
|
+
Utils.functionIdToString(FunctionId.random),
|
|
865
|
+
seed,
|
|
866
|
+
uint256(uint32(securityZone)),
|
|
867
|
+
inputs[1]
|
|
868
|
+
);
|
|
869
|
+
|
|
870
|
+
// NOTE: MOCK - the real task manager leaves the value to the coprocessor; store one here.
|
|
871
|
+
(MockGasMode mode, uint256 startGas) = _mockGasTrackStart();
|
|
872
|
+
_set(ctHash, uint256(keccak256(abi.encode(ctHash))));
|
|
873
|
+
_mockGasTrackEnd(mode, startGas);
|
|
874
|
+
|
|
875
|
+
return ctHash;
|
|
818
876
|
}
|
|
819
877
|
|
|
820
878
|
function isPubliclyAllowed(uint256 ctHash) external view returns (bool) {
|
|
821
|
-
|
|
879
|
+
return acl.globalAllowed(ctHash);
|
|
822
880
|
}
|
|
823
881
|
|
|
824
882
|
function verifyDecryptResultBatch(
|
|
@@ -826,7 +884,10 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
826
884
|
uint256[] calldata results,
|
|
827
885
|
bytes[] calldata signatures
|
|
828
886
|
) external view returns (bool) {
|
|
829
|
-
|
|
887
|
+
uint256 length = ctHashes.length;
|
|
888
|
+
if (results.length != length || signatures.length != length) revert LengthMismatch();
|
|
889
|
+
|
|
890
|
+
for (uint256 i = 0; i < length; i++) {
|
|
830
891
|
if (!_verifyDecryptResult(ctHashes[i], results[i], signatures[i], true)) {
|
|
831
892
|
return false;
|
|
832
893
|
}
|
|
@@ -839,8 +900,11 @@ contract MockTaskManager is ITaskManager, MockCoFHE {
|
|
|
839
900
|
uint256[] calldata results,
|
|
840
901
|
bytes[] calldata signatures
|
|
841
902
|
) external view returns (bool[] memory) {
|
|
842
|
-
|
|
843
|
-
|
|
903
|
+
uint256 length = ctHashes.length;
|
|
904
|
+
if (results.length != length || signatures.length != length) revert LengthMismatch();
|
|
905
|
+
|
|
906
|
+
bool[] memory out = new bool[](length);
|
|
907
|
+
for (uint256 i = 0; i < length; i++) {
|
|
844
908
|
out[i] = _verifyDecryptResult(ctHashes[i], results[i], signatures[i], false);
|
|
845
909
|
}
|
|
846
910
|
return out;
|
|
@@ -9,7 +9,7 @@ pragma solidity >=0.8.19 <0.9.0;
|
|
|
9
9
|
|
|
10
10
|
import { MockACL } from './MockACL.sol';
|
|
11
11
|
import { MockTaskManager } from './MockTaskManager.sol';
|
|
12
|
-
import {
|
|
12
|
+
import { ACP, PermissionedUpgradeable } from './Permissioned.sol';
|
|
13
13
|
|
|
14
14
|
contract MockThresholdNetwork {
|
|
15
15
|
MockTaskManager public mockTaskManager;
|
|
@@ -181,16 +181,16 @@ contract MockThresholdNetwork {
|
|
|
181
181
|
|
|
182
182
|
function decodeLowLevelReversion(bytes memory data) public pure returns (string memory error) {
|
|
183
183
|
bytes4 selector = bytes4(data);
|
|
184
|
-
if (selector ==
|
|
184
|
+
if (selector == PermissionedUpgradeable.PermissionInvalid_Expired.selector) {
|
|
185
185
|
return 'PermissionInvalid_Expired';
|
|
186
186
|
}
|
|
187
|
-
if (selector ==
|
|
187
|
+
if (selector == PermissionedUpgradeable.PermissionInvalid_IssuerSignature.selector) {
|
|
188
188
|
return 'PermissionInvalid_IssuerSignature';
|
|
189
189
|
}
|
|
190
|
-
if (selector ==
|
|
190
|
+
if (selector == PermissionedUpgradeable.PermissionInvalid_RecipientSignature.selector) {
|
|
191
191
|
return 'PermissionInvalid_RecipientSignature';
|
|
192
192
|
}
|
|
193
|
-
if (selector ==
|
|
193
|
+
if (selector == PermissionedUpgradeable.PermissionInvalid_Disabled.selector) {
|
|
194
194
|
return 'PermissionInvalid_Disabled';
|
|
195
195
|
}
|
|
196
196
|
// Handle other errors
|