@cofhe/mock-contracts 0.7.1 → 1.0.0-alpha.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.
@@ -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 {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
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 V3 permission struct.
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
- * Signing flows are identical to V2 (self / two-step sharing) with the
21
- * `ACPIssuerSelf` / `ACPIssuerShared` / `ACPRecipient` EIP-712 types under
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
- * Revocation: `revokerData` is an opaque uint256 interpreted by
25
- * `revokerContract` (creation timestamp in the default ACPTimestampRevoker).
26
- * `revokerData = 0` or `revokerContract = address(0)` disables the check
27
- * (permission not revocable).
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
- address issuer;
31
- uint64 expiration;
32
- address recipient;
33
- uint256 revokerData;
34
- address revokerContract;
35
- uint8 scope;
36
- address[] contracts;
37
- bytes32[] handles;
38
- bytes32 sealingKey;
39
- bytes issuerSignature;
40
- bytes recipientSignature;
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 control to disable a permission after creation.
97
+ /// Revokers are optional, and provide extra security and control when sharing permissions.
45
98
  interface IPermissionCustomIdValidator {
46
- /// @dev Returning `true` disables the permission.
47
- function disabled(address issuer, uint256 id) external view returns (bool);
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 MockPermissioned is EIP712 {
51
- using ACPUtils for ACP;
52
-
53
- /// @dev Same verifying-contract identity as V2 ("ACL"), domain version bumped for V3 types.
54
- constructor() EIP712("ACL", "2") {}
55
-
56
- error PermissionInvalid_Expired();
57
- error PermissionInvalid_IssuerSignature();
58
- error PermissionInvalid_RecipientSignature();
59
- error PermissionInvalid_Disabled();
60
-
61
- /// @dev Validates an ACP's structure: expiration, signatures, revocation.
62
- /// Identical check order and semantics to V2 `withPermission`.
63
- ///
64
- /// NOTE: Functions protected by `withPermission` should return ONLY the sensitive data of `acp.issuer`.
65
- /// !! Returning data of `msg.sender` will leak sensitive values - `msg.sender` cannot be trusted in view functions !!
66
- modifier withPermission(ACP memory acp) {
67
- // Expiration
68
- if (acp.expiration < block.timestamp)
69
- revert PermissionInvalid_Expired();
70
-
71
- // Issuer signature
72
- if (
73
- !SignatureChecker.isValidSignatureNow(
74
- acp.issuer,
75
- _hashTypedDataV4(acp.issuerHash()),
76
- acp.issuerSignature
77
- )
78
- ) revert PermissionInvalid_IssuerSignature();
79
-
80
- // (if applicable) Recipient signature
81
- if (
82
- acp.recipient != address(0) &&
83
- !SignatureChecker.isValidSignatureNow(
84
- acp.recipient,
85
- _hashTypedDataV4(acp.recipientHash()),
86
- acp.recipientSignature
87
- )
88
- ) revert PermissionInvalid_RecipientSignature();
89
-
90
- // (if applicable) Externally disabled (revoked)
91
- if (
92
- acp.revokerData != 0 &&
93
- acp.revokerContract != address(0) &&
94
- IPermissionCustomIdValidator(acp.revokerContract).disabled(
95
- acp.issuer,
96
- acp.revokerData
97
- )
98
- ) revert PermissionInvalid_Disabled();
99
-
100
- _;
101
- }
102
-
103
- /// @dev Structure-validity probe (expiration / signatures / revocation).
104
- function checkPermissionValidity(
105
- ACP memory acp
106
- ) public view withPermission(acp) returns (bool) {
107
- return true;
108
- }
109
-
110
- function hashTypedDataV4(
111
- bytes32 structHash
112
- ) public view virtual returns (bytes32) {
113
- return _hashTypedDataV4(structHash);
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 Signature type hashes for ACP. Field order must match the struct and the
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
- function issuerHash(ACP memory acp) internal pure returns (bytes32) {
121
- if (acp.recipient == address(0)) return issuerSelfHash(acp);
122
- return issuerSharedHash(acp);
123
- }
124
-
125
- function issuerSelfHash(ACP memory acp) internal pure returns (bytes32) {
126
- return
127
- keccak256(
128
- abi.encode(
129
- keccak256(
130
- "ACPIssuerSelf(address issuer,uint64 expiration,address recipient,uint256 revokerData,address revokerContract,uint8 scope,address[] contracts,bytes32[] handles,bytes32 sealingKey)"
131
- ),
132
- acp.issuer,
133
- acp.expiration,
134
- acp.recipient,
135
- acp.revokerData,
136
- acp.revokerContract,
137
- acp.scope,
138
- keccak256(abi.encodePacked(acp.contracts)),
139
- keccak256(abi.encodePacked(acp.handles)),
140
- acp.sealingKey
141
- )
142
- );
143
- }
144
-
145
- function issuerSharedHash(ACP memory acp) internal pure returns (bytes32) {
146
- return
147
- keccak256(
148
- abi.encode(
149
- keccak256(
150
- "ACPIssuerShared(address issuer,uint64 expiration,address recipient,uint256 revokerData,address revokerContract,uint8 scope,address[] contracts,bytes32[] handles)"
151
- ),
152
- acp.issuer,
153
- acp.expiration,
154
- acp.recipient,
155
- acp.revokerData,
156
- acp.revokerContract,
157
- acp.scope,
158
- keccak256(abi.encodePacked(acp.contracts)),
159
- keccak256(abi.encodePacked(acp.handles))
160
- )
161
- );
162
- }
163
-
164
- function recipientHash(ACP memory acp) internal pure returns (bytes32) {
165
- return
166
- keccak256(
167
- abi.encode(
168
- keccak256("ACPRecipient(bytes32 sealingKey,bytes issuerSignature)"),
169
- acp.sealingKey,
170
- keccak256(acp.issuerSignature)
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
+ }