@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
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
pragma solidity >=0.8.19 <0.9.0;
|
|
4
4
|
|
|
5
5
|
import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
|
|
6
|
-
import {
|
|
6
|
+
import {EIP712Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol";
|
|
7
|
+
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
|
7
8
|
|
|
8
9
|
/// @dev ACP scope discriminator (uint8 on the wire). Exactly one scope mode per ACP:
|
|
9
10
|
/// SCOPE_GLOBAL — access to ALL of `issuer`s encrypted values; `contracts`/`handles` must be empty
|
|
@@ -15,160 +16,256 @@ uint8 constant SCOPE_CONTRACT = 1;
|
|
|
15
16
|
uint8 constant SCOPE_HANDLES = 2;
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
|
-
* @dev ACP (Access Control Permission) — the
|
|
19
|
+
* @dev ACP (Access Control Permission) — the permission body that must be passed to a
|
|
20
|
+
* contract to allow access to sensitive data.
|
|
19
21
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* domain version "2".
|
|
22
|
+
* The minimum permission to access a user's own data requires the fields
|
|
23
|
+
* < issuer, expiration, scope, sealingKey, issuerSignature >
|
|
23
24
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* ---
|
|
26
|
+
*
|
|
27
|
+
* If not sharing the permission, `issuer` signs a signature using the fields:
|
|
28
|
+
* < issuer, expiration, recipient, revokerData, revokerContract, scope, contracts, handles, sealingKey >
|
|
29
|
+
* This signature can now be used by `issuer` to access their own encrypted data.
|
|
30
|
+
*
|
|
31
|
+
* ---
|
|
32
|
+
*
|
|
33
|
+
* Sharing a permission is a two step process: `issuer` completes step 1, and `recipient` completes step 2.
|
|
34
|
+
*
|
|
35
|
+
* 1:
|
|
36
|
+
* `issuer` creates a permission with `recipient` populated with the address of the user to give access to.
|
|
37
|
+
* `issuer` does not include a `sealingKey` in the permission, it will be populated by the `recipient`.
|
|
38
|
+
* `issuer` signs a signature including the fields: (note: `sealingKey` is absent in this signature)
|
|
39
|
+
* < issuer, expiration, recipient, revokerData, revokerContract, scope, contracts, handles >
|
|
40
|
+
* `issuer` packages the permission data and `issuerSignature` and shares it with `recipient`
|
|
41
|
+
* ** None of this data is sensitive, and can be shared as cleartext **
|
|
42
|
+
*
|
|
43
|
+
* 2:
|
|
44
|
+
* `recipient` adds their `sealingKey` to the data received from `issuer`
|
|
45
|
+
* `recipient` signs a signature including the fields:
|
|
46
|
+
* < sealingKey, issuerSignature >
|
|
47
|
+
* `recipient` can now use the completed permission to access `issuer`s encrypted data.
|
|
48
|
+
*
|
|
49
|
+
* ---
|
|
50
|
+
*
|
|
51
|
+
* Scope: `scope` selects exactly one access mode (see SCOPE_* above). Scopes narrow the
|
|
52
|
+
* issuer's existing ACL access, they never widen it. Scope semantics are enforced by the
|
|
53
|
+
* ACL (`isAllowedWithPermission`); this contract checks structure only.
|
|
54
|
+
*
|
|
55
|
+
* ---
|
|
56
|
+
*
|
|
57
|
+
* Revocation: `revokerData` and `revokerContract` are optional and can be used together to
|
|
58
|
+
* increase security and control by disabling a permission after it has been created.
|
|
59
|
+
* `revokerData` is an opaque uint256 interpreted by `revokerContract` (the creation
|
|
60
|
+
* timestamp in the default ACPTimestampRevoker). `revokerData = 0` or
|
|
61
|
+
* `revokerContract = address(0)` disables the check (permission not revocable).
|
|
28
62
|
*/
|
|
29
63
|
struct ACP {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
64
|
+
// (base) User that initially created the permission, target of data fetching
|
|
65
|
+
address issuer;
|
|
66
|
+
// (base) Expiration timestamp
|
|
67
|
+
uint64 expiration;
|
|
68
|
+
// (sharing) The user that this permission will be shared with
|
|
69
|
+
// ** optional, use `address(0)` to disable **
|
|
70
|
+
address recipient;
|
|
71
|
+
// (issuer defined revocation) Opaque data passed to `revokerContract` to check this permission's validity
|
|
72
|
+
// ** optional, use `0` to disable **
|
|
73
|
+
uint256 revokerData;
|
|
74
|
+
// (issuer defined revocation) The contract to query to determine permission validity
|
|
75
|
+
// ** optional, use `address(0)` to disable **
|
|
76
|
+
address revokerContract;
|
|
77
|
+
// (scope) Which access mode this permission grants — one of SCOPE_GLOBAL / SCOPE_CONTRACT / SCOPE_HANDLES
|
|
78
|
+
uint8 scope;
|
|
79
|
+
// (scope) Contracts whose readable values this permission grants access to (SCOPE_CONTRACT only)
|
|
80
|
+
address[] contracts;
|
|
81
|
+
// (scope) Ciphertext handles this permission grants access to (SCOPE_HANDLES only)
|
|
82
|
+
bytes32[] handles;
|
|
83
|
+
// (base) The publicKey of a sealingPair used to re-encrypt `issuer`s confidential data
|
|
84
|
+
// (non-sharing) Populated by `issuer`
|
|
85
|
+
// (sharing) Populated by `recipient`
|
|
86
|
+
bytes32 sealingKey;
|
|
87
|
+
// (base) `signTypedData` signature created by `issuer`.
|
|
88
|
+
// (base) Shared- and Self- permissions differ in signature format: (`sealingKey` absent in shared signature)
|
|
89
|
+
bytes issuerSignature;
|
|
90
|
+
// (sharing) `signTypedData` signature created by `recipient` with format:
|
|
91
|
+
// (sharing) < sealingKey, issuerSignature >
|
|
92
|
+
// ** required for shared permissions **
|
|
93
|
+
bytes recipientSignature;
|
|
41
94
|
}
|
|
42
95
|
|
|
43
96
|
/// @dev Minimum required interface to create a custom permission revoker.
|
|
44
|
-
/// Revokers are optional and provide
|
|
97
|
+
/// Revokers are optional, and provide extra security and control when sharing permissions.
|
|
45
98
|
interface IPermissionCustomIdValidator {
|
|
46
|
-
|
|
47
|
-
|
|
99
|
+
/// @dev Checks whether a permission has been revoked, returning `true` disables the permission.
|
|
100
|
+
function disabled(address issuer, uint256 id) external view returns (bool);
|
|
48
101
|
}
|
|
49
102
|
|
|
50
|
-
contract
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
103
|
+
contract PermissionedUpgradeable is Initializable, EIP712Upgradeable {
|
|
104
|
+
using ACPUtils for ACP;
|
|
105
|
+
|
|
106
|
+
/// @dev Same verifying-contract identity as V2 ("ACL"), domain version bumped for the ACP types.
|
|
107
|
+
function __PermissionedUpgradeable_init() internal onlyInitializing {
|
|
108
|
+
__EIP712_init_unchained("ACL", "2");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function __PermissionedUpgradeable_init_unchained()
|
|
112
|
+
internal
|
|
113
|
+
onlyInitializing
|
|
114
|
+
{
|
|
115
|
+
__EIP712_init_unchained("ACL", "2");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/// @dev The EIP-712 domain is defined by code, not by storage.
|
|
119
|
+
///
|
|
120
|
+
/// `EIP712Upgradeable` persists name/version at initialization time and only
|
|
121
|
+
/// then — an implementation-only upgrade would leave an already-initialized
|
|
122
|
+
/// proxy reporting the V2 domain ("ACL", "1") while hashing the V3 types,
|
|
123
|
+
/// and every signature would fail to verify. Overriding the accessors (which
|
|
124
|
+
/// OZ marks `virtual` for exactly this case) makes the upgrade a pure
|
|
125
|
+
/// implementation swap: no reinitializer, no migration transaction.
|
|
126
|
+
function _EIP712Name() internal view virtual override returns (string memory) {
|
|
127
|
+
return "ACL";
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function _EIP712Version()
|
|
131
|
+
internal
|
|
132
|
+
view
|
|
133
|
+
virtual
|
|
134
|
+
override
|
|
135
|
+
returns (string memory)
|
|
136
|
+
{
|
|
137
|
+
return "2";
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/// @dev Emitted when `acp.expiration` is in the past (< block.timestamp)
|
|
141
|
+
error PermissionInvalid_Expired();
|
|
142
|
+
|
|
143
|
+
/// @dev Emitted when `issuerSignature` is malformed or was not signed by `acp.issuer`
|
|
144
|
+
error PermissionInvalid_IssuerSignature();
|
|
145
|
+
|
|
146
|
+
/// @dev Emitted when `recipientSignature` is malformed or was not signed by `acp.recipient`
|
|
147
|
+
error PermissionInvalid_RecipientSignature();
|
|
148
|
+
|
|
149
|
+
/// @dev Emitted when `revokerContract` returned `true` indicating that this permission has been externally disabled
|
|
150
|
+
error PermissionInvalid_Disabled();
|
|
151
|
+
|
|
152
|
+
/// @dev Validates an `acp`s access of sensitive data.
|
|
153
|
+
/// `acp` may be invalid or unauthorized for the following reasons:
|
|
154
|
+
/// - Expired: `acp.expiration` is in the past (< block.timestamp)
|
|
155
|
+
/// - Issuer signature: `issuerSignature` is malformed or was not signed by `acp.issuer`
|
|
156
|
+
/// - Recipient signature: `recipientSignature` is malformed or was not signed by `acp.recipient`
|
|
157
|
+
/// - Disabled: `revokerContract` returned `true` indicating that this permission has been externally disabled
|
|
158
|
+
/// @param acp ACP struct containing data necessary to validate data access and seal for return.
|
|
159
|
+
///
|
|
160
|
+
/// NOTE: Functions protected by `withPermission` should return ONLY the sensitive data of `acp.issuer`.
|
|
161
|
+
/// !! Returning data of `msg.sender` will leak sensitive values - `msg.sender` cannot be trusted in view functions !!
|
|
162
|
+
modifier withPermission(ACP memory acp) {
|
|
163
|
+
// Expiration
|
|
164
|
+
if (acp.expiration < block.timestamp)
|
|
165
|
+
revert PermissionInvalid_Expired();
|
|
166
|
+
|
|
167
|
+
// Issuer signature
|
|
168
|
+
if (
|
|
169
|
+
!SignatureChecker.isValidSignatureNow(
|
|
170
|
+
acp.issuer,
|
|
171
|
+
_hashTypedDataV4(acp.issuerHash()),
|
|
172
|
+
acp.issuerSignature
|
|
173
|
+
)
|
|
174
|
+
) revert PermissionInvalid_IssuerSignature();
|
|
175
|
+
|
|
176
|
+
// (if applicable) Recipient signature
|
|
177
|
+
if (
|
|
178
|
+
acp.recipient != address(0) &&
|
|
179
|
+
!SignatureChecker.isValidSignatureNow(
|
|
180
|
+
acp.recipient,
|
|
181
|
+
_hashTypedDataV4(acp.recipientHash()),
|
|
182
|
+
acp.recipientSignature
|
|
183
|
+
)
|
|
184
|
+
) revert PermissionInvalid_RecipientSignature();
|
|
185
|
+
|
|
186
|
+
// (if applicable) Externally disabled (revoked)
|
|
187
|
+
if (
|
|
188
|
+
acp.revokerData != 0 &&
|
|
189
|
+
acp.revokerContract != address(0) &&
|
|
190
|
+
IPermissionCustomIdValidator(acp.revokerContract).disabled(
|
|
191
|
+
acp.issuer,
|
|
192
|
+
acp.revokerData
|
|
193
|
+
)
|
|
194
|
+
) revert PermissionInvalid_Disabled();
|
|
195
|
+
|
|
196
|
+
_;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/// @dev Structure-validity probe (expiration / signatures / revocation).
|
|
200
|
+
function checkPermissionValidity(
|
|
201
|
+
ACP memory acp
|
|
202
|
+
) public view withPermission(acp) returns (bool) {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
115
205
|
}
|
|
116
206
|
|
|
117
|
-
/// @dev
|
|
207
|
+
/// @dev Internal utility library to improve the readability of PermissionedUpgradeable.
|
|
208
|
+
/// Primarily focused on signature type hashes. Field order must match the struct and the
|
|
118
209
|
/// SDK's SignatureTypes exactly — pinned by tests on both sides.
|
|
119
210
|
library ACPUtils {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
211
|
+
function issuerHash(ACP memory acp) internal pure returns (bytes32) {
|
|
212
|
+
if (acp.recipient == address(0)) return issuerSelfHash(acp);
|
|
213
|
+
return issuerSharedHash(acp);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function issuerSelfHash(
|
|
217
|
+
ACP memory acp
|
|
218
|
+
) internal pure returns (bytes32) {
|
|
219
|
+
return
|
|
220
|
+
keccak256(
|
|
221
|
+
abi.encode(
|
|
222
|
+
keccak256(
|
|
223
|
+
"ACPIssuerSelf(address issuer,uint64 expiration,address recipient,uint256 revokerData,address revokerContract,uint8 scope,address[] contracts,bytes32[] handles,bytes32 sealingKey)"
|
|
224
|
+
),
|
|
225
|
+
acp.issuer,
|
|
226
|
+
acp.expiration,
|
|
227
|
+
acp.recipient,
|
|
228
|
+
acp.revokerData,
|
|
229
|
+
acp.revokerContract,
|
|
230
|
+
acp.scope,
|
|
231
|
+
keccak256(abi.encodePacked(acp.contracts)),
|
|
232
|
+
keccak256(abi.encodePacked(acp.handles)),
|
|
233
|
+
acp.sealingKey
|
|
234
|
+
)
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function issuerSharedHash(
|
|
239
|
+
ACP memory acp
|
|
240
|
+
) internal pure returns (bytes32) {
|
|
241
|
+
return
|
|
242
|
+
keccak256(
|
|
243
|
+
abi.encode(
|
|
244
|
+
keccak256(
|
|
245
|
+
"ACPIssuerShared(address issuer,uint64 expiration,address recipient,uint256 revokerData,address revokerContract,uint8 scope,address[] contracts,bytes32[] handles)"
|
|
246
|
+
),
|
|
247
|
+
acp.issuer,
|
|
248
|
+
acp.expiration,
|
|
249
|
+
acp.recipient,
|
|
250
|
+
acp.revokerData,
|
|
251
|
+
acp.revokerContract,
|
|
252
|
+
acp.scope,
|
|
253
|
+
keccak256(abi.encodePacked(acp.contracts)),
|
|
254
|
+
keccak256(abi.encodePacked(acp.handles))
|
|
255
|
+
)
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function recipientHash(
|
|
260
|
+
ACP memory acp
|
|
261
|
+
) internal pure returns (bytes32) {
|
|
262
|
+
return
|
|
263
|
+
keccak256(
|
|
264
|
+
abi.encode(
|
|
265
|
+
keccak256("ACPRecipient(bytes32 sealingKey,bytes issuerSignature)"),
|
|
266
|
+
acp.sealingKey,
|
|
267
|
+
keccak256(acp.issuerSignature)
|
|
268
|
+
)
|
|
269
|
+
);
|
|
270
|
+
}
|
|
174
271
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"repo": "FhenixProtocol/cofhe-contracts",
|
|
3
|
+
"commit": "0afc699c29e64c16e602845d95b2e85d5ca159c4",
|
|
4
|
+
"sourceDir": "contracts/internal/host-chain/contracts",
|
|
5
|
+
"files": {
|
|
6
|
+
"ACPShareRegistry.sol": "27cfcadd82922ca56151ae4bde04fff8129aa1c26d4631a2e16a56d6a96a9971",
|
|
7
|
+
"ACPTimestampRevoker.sol": "be40add6302b68cff8c15fb5bcc54e7ef74db63df59cf350e8ccfbb06a7a74fc",
|
|
8
|
+
"Permissioned.sol": "34d8d2f4a41c9a5ffbd69e32e4e3d718a7d4fcde6289fbe132fa3c4a74de9c0d"
|
|
9
|
+
}
|
|
10
|
+
}
|