@inco/lightning 0.6.1 → 0.6.5

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.
Files changed (43) hide show
  1. package/package.json +1 -1
  2. package/src/DeployUtils.sol +1 -1
  3. package/src/Errors.sol +1 -1
  4. package/src/Lib.alphanet.sol +24 -3
  5. package/src/Lib.demonet.sol +24 -3
  6. package/src/Lib.devnet.sol +24 -3
  7. package/src/Lib.sol +24 -3
  8. package/src/Lib.template.sol +97 -20
  9. package/src/Lib.testnet.sol +24 -3
  10. package/src/libs/incoLightning_alphanet_v0_297966649.sol +24 -3
  11. package/src/libs/incoLightning_alphanet_v1_725458969.sol +24 -3
  12. package/src/libs/incoLightning_demonet_v0_863421733.sol +24 -3
  13. package/src/libs/incoLightning_devnet_v0_340846814.sol +24 -3
  14. package/src/libs/incoLightning_devnet_v1_904635675.sol +24 -3
  15. package/src/libs/incoLightning_testnet_v0_183408998.sol +24 -3
  16. package/src/lightning-parts/AccessControl/test/TestAdvancedAccessControl.t.sol +1 -1
  17. package/src/lightning-parts/EncryptedInput.sol +52 -16
  18. package/src/lightning-parts/EncryptedOperations.sol +86 -90
  19. package/src/lightning-parts/TEELifecycle.sol +153 -66
  20. package/src/lightning-parts/TEELifecycle.types.sol +7 -0
  21. package/src/lightning-parts/interfaces/ITEELifecycle.sol +13 -2
  22. package/src/lightning-parts/primitives/HandleGeneration.sol +23 -57
  23. package/src/lightning-parts/primitives/interfaces/IHandleGeneration.sol +3 -34
  24. package/src/lightning-parts/test/HandleMetadata.t.sol +41 -4
  25. package/src/lightning-parts/test/InputsFee.t.sol +14 -21
  26. package/src/lightning-parts/test/TestDecryptionAttestationInSynchronousFlow.t.sol +6 -2
  27. package/src/shared/IOwnable.sol +10 -0
  28. package/src/shared/IUUPSUpgradable.sol +10 -0
  29. package/src/shared/JsonUtils.sol +16 -0
  30. package/src/shared/TestUtils.sol +50 -0
  31. package/src/shared/TypeUtils.sol +12 -0
  32. package/src/test/FakeIncoInfra/FakeComputeServer.sol +1 -1
  33. package/src/test/FakeIncoInfra/FakeDecryptionAttester.sol +36 -34
  34. package/src/test/FakeIncoInfra/FakeIncoInfraBase.sol +33 -18
  35. package/src/test/FakeIncoInfra/KVStore.sol +1 -1
  36. package/src/test/FakeIncoInfra/MockOpHandler.sol +5 -5
  37. package/src/test/FakeIncoInfra/MockRemoteAttestation.sol +1 -1
  38. package/src/test/IncoTest.sol +1 -1
  39. package/src/test/TEELifecycle/TEELifecycleMockTest.t.sol +73 -20
  40. package/src/test/TestAddTwo.t.sol +1 -1
  41. package/src/test/TestFakeInfra.t.sol +13 -3
  42. package/src/version/Version.sol +4 -0
  43. package/src/version/interfaces/IVersion.sol +1 -0
@@ -1,9 +1,6 @@
1
1
  pragma solidity ^0.8.19;
2
2
 
3
- import {
4
- BootstrapResult,
5
- UpgradeResult
6
- } from "./TEELifecycle.types.sol";
3
+ import {BootstrapResult, UpgradeResult, AddNodeResult} from "./TEELifecycle.types.sol";
7
4
  import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
8
5
  import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
9
6
  import {IQuoteVerifier} from "../interfaces/automata-interfaces/IQuoteVerifier.sol";
@@ -21,8 +18,37 @@ import {
21
18
  import {IFmspcTcbDao} from "../interfaces/automata-interfaces/IFmspcTcbDao.sol";
22
19
  import {IAutomataEnclaveIdentityDao} from "../interfaces/automata-interfaces/IAutomataEnclaveIdentityDao.sol";
23
20
 
24
- // todo #1031 make TEELifecycle storage upgrade compatible
21
+ contract TEELifecycleStorage {
22
+ struct StorageForTEELifecycle {
23
+ IQuoteVerifier quoteVerifier;
24
+ BootstrapResult VerifiedBootstrapResult;
25
+ bool BootstrapComplete;
26
+ // @notice The list of approved TEE versions, each item is the MR_AGGREGATED 32 bytes
27
+ // @dev The index of the TEE version is the version number
28
+ bytes32[] ApprovedTEEVersions;
29
+ // @notice The Network key
30
+ // @todo rename to NetworkPubkey https://github.com/Inco-fhevm/inco-monorepo/issues/983
31
+ bytes ECIESPubkey;
32
+ mapping(address => bool) EOASigners;
33
+ }
34
+
35
+ bytes32 private constant TEELifecycleStorageLocation =
36
+ keccak256("inco.storage.TEELifecycle");
37
+
38
+ function getTEELifecycleStorage()
39
+ internal
40
+ pure
41
+ returns (StorageForTEELifecycle storage $)
42
+ {
43
+ bytes32 loc = TEELifecycleStorageLocation;
44
+ assembly {
45
+ $.slot := loc
46
+ }
47
+ }
48
+ }
49
+
25
50
  abstract contract TEELifecycle is
51
+ TEELifecycleStorage,
26
52
  ITEELifecycle,
27
53
  OwnableUpgradeable,
28
54
  EIP712Upgradeable
@@ -37,6 +63,7 @@ abstract contract TEELifecycle is
37
63
  error TEEVersionNotFound();
38
64
  error InvalidReportMrAggregated();
39
65
  error InvalidReportDataSigner();
66
+ error IndexOutOfBounds();
40
67
  /// @notice The EIP712 signature recovered an incorrect address
41
68
  error InvalidEIP712Signature();
42
69
  error EOASignerAlreadyInitialized();
@@ -47,7 +74,10 @@ abstract contract TEELifecycle is
47
74
 
48
75
  // Events
49
76
  // @notice A new MR_AGGREGATED has been approved
50
- event NewTEEVersionApproved(uint256 indexed version, bytes32 indexed mrAggregated);
77
+ event NewTEEVersionApproved(
78
+ uint256 indexed version,
79
+ bytes32 indexed mrAggregated
80
+ );
51
81
  event NewCovalidatorAdded(address covalidatorAddress, bytes quote);
52
82
  event BootstrapStageComplete(
53
83
  address indexed newEOASigner,
@@ -57,31 +87,26 @@ abstract contract TEELifecycle is
57
87
  // MR_AGGREGATED. This is done by checking remote attestation of the quote
58
88
  // and verifying the EIP712 signature of the bootstrap/upgrade result by
59
89
  // the TDX EOA.
60
- event EOAHasUpdatedTDX(address indexed eoaSigner, bytes32 indexed mrAggregated);
90
+ event EOAHasUpdatedTDX(
91
+ address indexed eoaSigner,
92
+ bytes32 indexed mrAggregated
93
+ );
61
94
 
62
95
  // Constants
63
96
  bytes32 public constant BootstrapResultStructHash =
64
97
  keccak256(bytes("BootstrapResult(bytes ecies_pubkey)"));
65
98
  bytes32 public constant UpgradeResultStructHash =
66
99
  keccak256(bytes("UpgradeResult(bytes network_pubkey)"));
100
+ bytes32 public constant AddNodeResultStructHash =
101
+ keccak256(bytes("AddNodeResult(bytes network_pubkey)"));
67
102
 
68
103
  uint16 public constant QUOTE_VERIFIER_VERSION = 4;
69
104
 
70
- IQuoteVerifier public quoteVerifier;
71
-
72
- // @notice The list of approved TEE versions, each item is the MR_AGGREGATED 32 bytes
73
- // @dev The index of the TEE version is the version number
74
- bytes32[] public ApprovedTEEVersions;
75
- // @notice The Network key
76
- // @todo rename to NetworkPubkey https://github.com/Inco-fhevm/inco-monorepo/issues/983
77
- bytes public ECIESPubkey;
78
- mapping(address => bool) public EOASigners;
79
-
80
105
  function __TEELifecycle_init(
81
106
  IQuoteVerifier _quoteVerifier
82
107
  ) internal onlyInitializing {
83
- quoteVerifier = _quoteVerifier;
84
- uint16 actualQuoteVerifierVersion = quoteVerifier.quoteVersion();
108
+ getTEELifecycleStorage().quoteVerifier = _quoteVerifier;
109
+ uint16 actualQuoteVerifierVersion = _quoteVerifier.quoteVersion();
85
110
  require(
86
111
  actualQuoteVerifierVersion == QUOTE_VERIFIER_VERSION,
87
112
  InvalidQuoteVerifierVersion(
@@ -103,12 +128,14 @@ abstract contract TEELifecycle is
103
128
  require(bytes(tcbInfo.tcbInfoStr).length != 0, EmptyTcbInfo());
104
129
  require(bytes(identity.identityStr).length != 0, EmptyIdentity());
105
130
 
131
+ IQuoteVerifier _quoteVerifier = quoteVerifier();
132
+
106
133
  IFmspcTcbDao fmspcTcbDao = IFmspcTcbDao(
107
- quoteVerifier.pccsRouter().fmspcTcbDaoAddr()
134
+ _quoteVerifier.pccsRouter().fmspcTcbDaoAddr()
108
135
  );
109
136
  fmspcTcbDao.upsertFmspcTcb(tcbInfo);
110
137
  IAutomataEnclaveIdentityDao enclaveIdDao = IAutomataEnclaveIdentityDao(
111
- quoteVerifier.pccsRouter().qeIdDaoAddr()
138
+ _quoteVerifier.pccsRouter().qeIdDaoAddr()
112
139
  );
113
140
  (IdentityObj memory identityObj, ) = enclaveIdDao
114
141
  .EnclaveIdentityLib()
@@ -131,14 +158,16 @@ abstract contract TEELifecycle is
131
158
  bytes calldata quote,
132
159
  bytes calldata signature
133
160
  ) public onlyOwner {
161
+ StorageForTEELifecycle storage $ = getTEELifecycleStorage();
162
+
134
163
  // Make sure the bootstrap is not already complete, and that the contract owner
135
164
  // has already submitted the pending TEE MR_AGGREGATED.
136
165
  require(!isBootstrapComplete(), BootstrapAlreadyCompleted());
137
- require(ApprovedTEEVersions.length == 1, TEEVersionNotFound());
166
+ require($.ApprovedTEEVersions.length == 1, TEEVersionNotFound());
138
167
 
139
168
  bytes32 digest = bootstrapResultDigest(bootstrapResult);
140
169
  address reportDataSigner = _verifyResultForEOA(
141
- ApprovedTEEVersions[0],
170
+ $.ApprovedTEEVersions[0],
142
171
  digest,
143
172
  quote,
144
173
  signature
@@ -148,8 +177,8 @@ abstract contract TEELifecycle is
148
177
  // So if we arrive here in code, it means that the EOA has signed the bootstrap result
149
178
 
150
179
  // Update contract publicly viewable state
151
- ECIESPubkey = bootstrapResult.ecies_pubkey;
152
- EOASigners[reportDataSigner] = true;
180
+ $.ECIESPubkey = bootstrapResult.ecies_pubkey;
181
+ $.EOASigners[reportDataSigner] = true;
153
182
 
154
183
  emit BootstrapStageComplete(reportDataSigner, bootstrapResult);
155
184
  }
@@ -167,9 +196,14 @@ abstract contract TEELifecycle is
167
196
  bytes calldata quote,
168
197
  bytes calldata signature
169
198
  ) public {
199
+ StorageForTEELifecycle storage $ = getTEELifecycleStorage();
200
+
170
201
  require(isBootstrapComplete(), BootstrapNotComplete());
171
202
  // Make sure the quote's network pubkey is the same as the one in the bootstrap result
172
- require(keccak256(ECIESPubkey) == keccak256(upgradeResult.network_pubkey), InvalidNetworkPubkey());
203
+ require(
204
+ keccak256($.ECIESPubkey) == keccak256(upgradeResult.network_pubkey),
205
+ InvalidNetworkPubkey()
206
+ );
173
207
  // Make sure the new MR_AGGREGATED has been pre-approved.
174
208
  bool isApproved = _isApprovedTEEVersion(newMrAggregated);
175
209
  require(isApproved, TEEVersionNotFound());
@@ -182,7 +216,41 @@ abstract contract TEELifecycle is
182
216
  signature
183
217
  );
184
218
  // Make sure the new EOA signer is an existing EOA signer
185
- require(EOASigners[reportDataSigner], EOASignerNotFound());
219
+ require($.EOASigners[reportDataSigner], EOASignerNotFound());
220
+ }
221
+
222
+ /**
223
+ * @notice Verifies the add node result, and adds the new EOA signer to the contract state.
224
+ * @param quote - The quote from the new covalidator that contains the current MR_AGGREGATED and the eoa address of the new party in the report data
225
+ */
226
+ function verifyAddNodeResult(
227
+ bytes32 newMrAggregated,
228
+ AddNodeResult calldata addNodeResult,
229
+ bytes calldata quote,
230
+ bytes calldata signature
231
+ ) public onlyOwner {
232
+ StorageForTEELifecycle storage $ = getTEELifecycleStorage();
233
+
234
+ require(isBootstrapComplete(), BootstrapNotComplete());
235
+ // Make sure the quote's network pubkey is the same as the one in the bootstrap result
236
+ require(
237
+ keccak256($.ECIESPubkey) == keccak256(addNodeResult.network_pubkey),
238
+ InvalidNetworkPubkey()
239
+ );
240
+ // Make sure the new MR_AGGREGATED has been pre-approved.
241
+ bool isApproved = _isApprovedTEEVersion(newMrAggregated);
242
+ require(isApproved, TEEVersionNotFound());
243
+
244
+ bytes32 digest = addNodeResultDigest(addNodeResult);
245
+ address reportDataSigner = _verifyResultForEOA(
246
+ newMrAggregated,
247
+ digest,
248
+ quote,
249
+ signature
250
+ );
251
+
252
+ // Add this new EOA signer as a new signer to the contract state
253
+ $.EOASigners[reportDataSigner] = true;
186
254
  }
187
255
 
188
256
  /**
@@ -192,13 +260,20 @@ abstract contract TEELifecycle is
192
260
  * @dev This function increments the version number automatically based on the current history
193
261
  */
194
262
  function approveNewTEEVersion(bytes32 newMrAggregated) public onlyOwner {
195
- ApprovedTEEVersions.push(newMrAggregated);
196
- emit NewTEEVersionApproved(ApprovedTEEVersions.length - 1, newMrAggregated);
263
+ StorageForTEELifecycle storage $ = getTEELifecycleStorage();
264
+ $.ApprovedTEEVersions.push(newMrAggregated);
265
+ emit NewTEEVersionApproved(
266
+ $.ApprovedTEEVersions.length - 1,
267
+ newMrAggregated
268
+ );
197
269
  }
198
270
 
199
- function _isApprovedTEEVersion(bytes32 newMrAggregated) internal view returns (bool) {
200
- for (uint256 i = 0; i < ApprovedTEEVersions.length; i++) {
201
- if (ApprovedTEEVersions[i] == newMrAggregated) {
271
+ function _isApprovedTEEVersion(
272
+ bytes32 newMrAggregated
273
+ ) internal view returns (bool) {
274
+ StorageForTEELifecycle storage $ = getTEELifecycleStorage();
275
+ for (uint256 i = 0; i < $.ApprovedTEEVersions.length; i++) {
276
+ if ($.ApprovedTEEVersions[i] == newMrAggregated) {
202
277
  return true;
203
278
  }
204
279
  }
@@ -230,43 +305,14 @@ abstract contract TEELifecycle is
230
305
  reportMrAggregated == newMrAggregated,
231
306
  InvalidReportMrAggregated()
232
307
  );
233
- address recoveredAddress = ECDSA.recover(
234
- resultEip712Digest,
235
- signature
236
- );
237
- require(
238
- recoveredAddress == reportDataSigner,
239
- InvalidEIP712Signature()
240
- );
308
+ address recoveredAddress = ECDSA.recover(resultEip712Digest, signature);
309
+ require(recoveredAddress == reportDataSigner, InvalidEIP712Signature());
241
310
 
242
311
  emit EOAHasUpdatedTDX(reportDataSigner, newMrAggregated);
243
312
 
244
313
  return reportDataSigner;
245
314
  }
246
315
 
247
- /**
248
- * @notice Adds a new covalidator to the contract state
249
- * @param quote - The quote from the new covalidator that contains the current MR_AGGREGATED and the eoa address of the new party in the report data
250
- */
251
- function addNewCovalidator(bytes calldata quote) public onlyOwner {
252
- require(isBootstrapComplete(), BootstrapNotComplete());
253
-
254
- (bool success, bytes memory output) = _verifyAndAttestOnChain(quote);
255
- require(success, string(output));
256
- TD10ReportBody memory tdReport = parseTD10ReportBody(quote);
257
- (address reportDataSigner, bytes32 reportMrAggregated) = parseReport(
258
- tdReport
259
- );
260
- require(!EOASigners[reportDataSigner], EOASignerAlreadyInitialized());
261
-
262
- bool isApproved = _isApprovedTEEVersion(reportMrAggregated);
263
- require(isApproved, TEEVersionNotFound());
264
-
265
- require(reportDataSigner != address(0), InvalidReportDataSigner());
266
- emit NewCovalidatorAdded(reportDataSigner, quote);
267
- EOASigners[reportDataSigner] = true;
268
- }
269
-
270
316
  /**
271
317
  * @notice Checks if the bootstrap is complete.
272
318
  * @return true if the bootstrap is complete, false otherwise
@@ -274,7 +320,7 @@ abstract contract TEELifecycle is
274
320
  function isBootstrapComplete() public view returns (bool) {
275
321
  // The network pubkey is set once and once only, during the bootstrap process
276
322
  // So we can use the length of the network pubkey to check if the bootstrap is complete
277
- return ECIESPubkey.length > 0;
323
+ return getTEELifecycleStorage().ECIESPubkey.length > 0;
278
324
  }
279
325
 
280
326
  /**
@@ -302,7 +348,10 @@ abstract contract TEELifecycle is
302
348
 
303
349
  // We found a supported version, begin verifying the quote
304
350
  // Note: The quote header cannot be trusted yet, it will be validated by the Verifier library
305
- (success, output) = quoteVerifier.verifyQuote(header, rawQuote);
351
+ (success, output) = getTEELifecycleStorage().quoteVerifier.verifyQuote(
352
+ header,
353
+ rawQuote
354
+ );
306
355
  }
307
356
 
308
357
  /**
@@ -397,7 +446,12 @@ abstract contract TEELifecycle is
397
446
  ) public pure returns (address, bytes32) {
398
447
  return (
399
448
  address(bytes20(tdReport.reportData)),
400
- computeMrAggregated(tdReport.mrTd, tdReport.rtMr0, tdReport.rtMr1, tdReport.rtMr2)
449
+ computeMrAggregated(
450
+ tdReport.mrTd,
451
+ tdReport.rtMr0,
452
+ tdReport.rtMr1,
453
+ tdReport.rtMr2
454
+ )
401
455
  );
402
456
  }
403
457
 
@@ -420,6 +474,26 @@ abstract contract TEELifecycle is
420
474
  return keccak256(message);
421
475
  }
422
476
 
477
+ function quoteVerifier() public view returns (IQuoteVerifier) {
478
+ return getTEELifecycleStorage().quoteVerifier;
479
+ }
480
+
481
+ function approvedTEEVersions(
482
+ uint256 index
483
+ ) external view returns (bytes32) {
484
+ StorageForTEELifecycle storage $ = getTEELifecycleStorage();
485
+ require(index < $.ApprovedTEEVersions.length, IndexOutOfBounds());
486
+ return $.ApprovedTEEVersions[index];
487
+ }
488
+
489
+ function eciesPubkey() external view returns (bytes memory) {
490
+ return getTEELifecycleStorage().ECIESPubkey;
491
+ }
492
+
493
+ function isEOASigner(address addr) external view returns (bool) {
494
+ return getTEELifecycleStorage().EOASigners[addr];
495
+ }
496
+
423
497
  function bootstrapResultDigest(
424
498
  BootstrapResult memory bootstrapResult
425
499
  ) public view returns (bytes32) {
@@ -447,4 +521,17 @@ abstract contract TEELifecycle is
447
521
  )
448
522
  );
449
523
  }
524
+
525
+ function addNodeResultDigest(
526
+ AddNodeResult memory addNodeResult
527
+ ) public view returns (bytes32) {
528
+ return
529
+ _hashTypedDataV4(
530
+ keccak256(abi.encode(
531
+ AddNodeResultStructHash,
532
+ keccak256(addNodeResult.network_pubkey)
533
+ )
534
+ )
535
+ );
536
+ }
450
537
  }
@@ -16,3 +16,10 @@ struct BootstrapResult {
16
16
  struct UpgradeResult {
17
17
  bytes network_pubkey;
18
18
  }
19
+
20
+ /**
21
+ * @notice A struct representing what the TDX EOA signs during the add node process.
22
+ */
23
+ struct AddNodeResult {
24
+ bytes network_pubkey;
25
+ }
@@ -1,7 +1,7 @@
1
1
  /// SPDX-License-Identifier: No License
2
2
  pragma solidity ^0.8.19;
3
3
 
4
- import {BootstrapResult} from "../TEELifecycle.types.sol";
4
+ import {BootstrapResult, UpgradeResult, AddNodeResult} from "../TEELifecycle.types.sol";
5
5
  import {IQuoteVerifier} from "../../interfaces/automata-interfaces/IQuoteVerifier.sol";
6
6
  import {TD10ReportBody} from "../../interfaces/automata-interfaces/Types.sol";
7
7
 
@@ -11,8 +11,19 @@ interface ITEELifecycle {
11
11
  bytes calldata quote,
12
12
  bytes calldata signature
13
13
  ) external;
14
+ function verifyUpgradeResult(
15
+ bytes32 newMrAggregated,
16
+ UpgradeResult calldata upgradeResult,
17
+ bytes calldata quote,
18
+ bytes calldata signature
19
+ ) external;
20
+ function verifyAddNodeResult(
21
+ bytes32 newMrAggregated,
22
+ AddNodeResult calldata addNodeResult,
23
+ bytes calldata quote,
24
+ bytes calldata signature
25
+ ) external;
14
26
  function approveNewTEEVersion(bytes32 newMrAggregated) external;
15
- function addNewCovalidator(bytes calldata quote) external;
16
27
  function parseTD10ReportBody(
17
28
  bytes calldata rawQuote
18
29
  ) external pure returns (TD10ReportBody memory report);
@@ -17,12 +17,8 @@ contract HandleGeneration is IHandleGeneration, HandleMetadata {
17
17
  ) public view returns (bytes32 generatedHandle) {
18
18
  generatedHandle = keccak256(
19
19
  abi.encodePacked(
20
- EVM_HOST_CHAIN_PREFIX,
21
- block.chainid, // todo cache this
22
- EOps.TrivialEncrypt,
23
- plaintextBytes,
24
- handleType,
25
- address(this) // todo cache this
20
+ EOps.TrivialEncrypt, // !! Note[Silas]: I reordered this to be first element for greater regularity 26/08/2025 (remove this note after 1 month) !!
21
+ plaintextBytes
26
22
  )
27
23
  );
28
24
  generatedHandle = embedTypeVersion(generatedHandle, handleType);
@@ -33,7 +29,24 @@ contract HandleGeneration is IHandleGeneration, HandleMetadata {
33
29
  address user,
34
30
  address contractAddress,
35
31
  ETypes inputType
36
- ) public view returns (bytes32 generatedHandle) {
32
+ ) internal view returns (bytes32 generatedHandle) {
33
+ return
34
+ getInputHandle(
35
+ ciphertext,
36
+ address(this),
37
+ user,
38
+ contractAddress,
39
+ inputType
40
+ );
41
+ }
42
+
43
+ function getInputHandle(
44
+ bytes memory ciphertext,
45
+ address executorAddress,
46
+ address user,
47
+ address contractAddress,
48
+ ETypes inputType
49
+ ) internal view returns (bytes32 generatedHandle) {
37
50
  // Here we ensure that our hashing scheme is binary-compatible between IncoLightning and IncoFhevm, this helps
38
51
  // keep client-side code consistent in its ciphertext, context => handle mappings
39
52
  bytes32 ctIndexHash = keccak256(
@@ -47,7 +60,7 @@ contract HandleGeneration is IHandleGeneration, HandleMetadata {
47
60
  prehandle,
48
61
  EVM_HOST_CHAIN_PREFIX,
49
62
  block.chainid, // todo cache this
50
- address(this), // todo cache this
63
+ executorAddress,
51
64
  user,
52
65
  contractAddress
53
66
  )
@@ -59,55 +72,8 @@ contract HandleGeneration is IHandleGeneration, HandleMetadata {
59
72
  function getOpResultHandle(
60
73
  EOps op,
61
74
  ETypes returnType,
62
- bytes32 lhs,
63
- bytes32 rhs
75
+ bytes memory packedInputs
64
76
  ) public pure returns (bytes32 generatedHandle) {
65
- generatedHandle = getOpResultHandle(
66
- keccak256(abi.encodePacked(op, lhs, rhs)),
67
- returnType
68
- );
69
- }
70
-
71
- function getOpResultHandle(
72
- EOps op,
73
- ETypes returnType,
74
- uint256 counter,
75
- bytes32 upperBound
76
- ) public pure returns (bytes32 generatedHandle) {
77
- generatedHandle = getOpResultHandle(
78
- keccak256(abi.encodePacked(op, counter, upperBound)),
79
- returnType
80
- );
81
- }
82
-
83
- function getOpResultHandle(
84
- EOps op,
85
- ETypes returnType,
86
- bytes32 value
87
- ) public pure returns (bytes32 generatedHandle) {
88
- generatedHandle = getOpResultHandle(
89
- keccak256(abi.encodePacked(op, value)),
90
- returnType
91
- );
92
- }
93
-
94
- function getOpResultHandle(
95
- EOps op,
96
- ETypes returnType,
97
- bytes32 inputA,
98
- bytes32 inputB,
99
- bytes32 inputC
100
- ) public pure returns (bytes32 generatedHandle) {
101
- generatedHandle = getOpResultHandle(
102
- keccak256(abi.encodePacked(op, inputA, inputB, inputC)),
103
- returnType
104
- );
105
- }
106
-
107
- function getOpResultHandle(
108
- bytes32 baseHandle,
109
- ETypes returnType
110
- ) internal pure returns (bytes32 generatedHandle) {
111
- generatedHandle = embedTypeVersion(baseHandle, returnType);
77
+ generatedHandle = embedTypeVersion(keccak256(abi.encodePacked(op, packedInputs)), returnType);
112
78
  }
113
79
  }
@@ -4,38 +4,7 @@ pragma solidity ^0.8;
4
4
  import {ETypes, EOps} from "../../../Types.sol";
5
5
 
6
6
  interface IHandleGeneration {
7
- function getTrivialEncryptHandle(
8
- bytes32 plaintextBytes,
9
- ETypes handleType
10
- ) external view returns (bytes32 generatedHandle);
11
- function getInputHandle(
12
- bytes memory ciphertext,
13
- address user,
14
- address contractAddress,
15
- ETypes inputType
16
- ) external view returns (bytes32 generatedHandle);
17
- function getOpResultHandle(
18
- EOps op,
19
- ETypes returnType,
20
- bytes32 lhs,
21
- bytes32 rhs
22
- ) external pure returns (bytes32 generatedHandle);
23
- function getOpResultHandle(
24
- EOps op,
25
- ETypes returnType,
26
- uint256 counter,
27
- bytes32 upperBound
28
- ) external pure returns (bytes32 generatedHandle);
29
- function getOpResultHandle(
30
- EOps op,
31
- ETypes returnType,
32
- bytes32 value
33
- ) external pure returns (bytes32 generatedHandle);
34
- function getOpResultHandle(
35
- EOps op,
36
- ETypes returnType,
37
- bytes32 inputA,
38
- bytes32 inputB,
39
- bytes32 inputC
40
- ) external pure returns (bytes32 generatedHandle);
7
+ function getTrivialEncryptHandle(bytes32 plaintextBytes, ETypes handleType) external view returns (bytes32 generatedHandle);
8
+
9
+ function getOpResultHandle(EOps op, ETypes returnType, bytes memory packedInputs) external pure returns (bytes32 generatedHandle);
41
10
  }
@@ -1,7 +1,7 @@
1
1
  // SPDX-License-Identifier: No License
2
2
  pragma solidity ^0.8;
3
3
 
4
- import {TestUtils} from "@inco/shared/src/TestUtils.sol";
4
+ import {TestUtils} from "../../shared/TestUtils.sol";
5
5
  import {HandleMetadata} from "../primitives/HandleMetadata.sol";
6
6
  import {TrivialEncryption} from "../TrivialEncryption.sol";
7
7
  import {EncryptedOperations} from "../EncryptedOperations.sol";
@@ -108,11 +108,48 @@ contract TestHandleMetadata is
108
108
  }
109
109
 
110
110
  function testEncryptedInputHandleType() public {
111
- euint256 a = this.newEuint256{value: FEE}("ciphertext", address(this));
111
+ address self = address(this);
112
+ bytes32 ciphertext = keccak256(abi.encodePacked("ciphertext"));
113
+ euint256 a = this.newEuint256{value: FEE}(
114
+ getCiphertextInput(ciphertext, self, self, ETypes.Uint256),
115
+ self
116
+ );
112
117
  assert(typeOf(euint256.unwrap(a)) == ETypes.Uint256);
113
- ebool b = this.newEbool{value: FEE}("ciphertext", address(this));
118
+ ebool b = this.newEbool{value: FEE}(
119
+ getCiphertextInput(ciphertext, self, self, ETypes.Bool),
120
+ address(this)
121
+ );
114
122
  assert(typeOf(ebool.unwrap(b)) == ETypes.Bool);
115
- eaddress c = this.newEaddress{value: FEE}("ciphertext", address(this));
123
+ eaddress c = this.newEaddress{value: FEE}(
124
+ getCiphertextInput(
125
+ ciphertext,
126
+ self,
127
+ self,
128
+ ETypes.AddressOrUint160OrBytes20
129
+ ),
130
+ address(this)
131
+ );
116
132
  assert(typeOf(eaddress.unwrap(c)) == ETypes.AddressOrUint160OrBytes20);
117
133
  }
134
+
135
+ /// @notice Helper to create an input with a handle prepended to the ciphertext.
136
+ /// @param word A single word to be used as the ciphertext.
137
+ /// @param user The user address associated with the input.
138
+ function getCiphertextInput(
139
+ bytes32 word,
140
+ address user,
141
+ address contractAddress,
142
+ ETypes inputType
143
+ ) public view returns (bytes memory input) {
144
+ // We need a single word here to get correct encoding
145
+ bytes memory ciphertext = abi.encode(word);
146
+ bytes32 handle = getInputHandle(
147
+ ciphertext,
148
+ address(this),
149
+ user,
150
+ contractAddress,
151
+ inputType
152
+ );
153
+ input = abi.encode(handle, ciphertext);
154
+ }
118
155
  }
@@ -6,59 +6,52 @@ import {EncryptedInput} from "../EncryptedInput.sol";
6
6
  import {VerifierAddressGetter} from "../primitives/VerifierAddressGetter.sol";
7
7
  import {FEE, Fee} from "../Fee.sol";
8
8
  import {IncoTest} from "../../test/IncoTest.sol";
9
-
10
- contract InputsTester is EncryptedInput {
11
- constructor() VerifierAddressGetter(address(0)) {}
12
- }
9
+ import {console} from "forge-std/console.sol";
10
+ import {inco} from "../../Lib.sol";
13
11
 
14
12
  contract TestInputsFee is IncoTest {
15
- InputsTester inputsTester;
16
-
17
- function setUp() public override {
18
- inputsTester = new InputsTester();
19
- }
20
13
 
21
14
  function testPayOnInputs() public {
22
15
  // should fail if no fee
23
16
  vm.expectRevert(Fee.FeeNotPaid.selector);
24
- inputsTester.newEuint256{value: 0}(
25
- fakePrepareEuint256Ciphertext(12),
17
+ inco.newEuint256{value: 0}(
18
+ fakePrepareEuint256Ciphertext(12, address(0), address(this)),
26
19
  address(0)
27
20
  );
28
21
 
29
22
  // should fail if not enough fee
30
23
  vm.expectRevert(Fee.FeeNotPaid.selector);
31
- inputsTester.newEuint256{value: FEE - 1}(
32
- fakePrepareEuint256Ciphertext(12),
24
+ inco.newEuint256{value: FEE - 1}(
25
+ fakePrepareEuint256Ciphertext(12, address(0), address(this)),
33
26
  address(0)
34
27
  );
35
28
 
36
29
  // should fail if too much fee
37
30
  vm.expectRevert(Fee.FeeNotPaid.selector);
38
- inputsTester.newEuint256{value: FEE + 1}(
39
- fakePrepareEuint256Ciphertext(12),
31
+ inco.newEuint256{value: FEE + 1}(
32
+ fakePrepareEuint256Ciphertext(12, address(0), address(this)),
40
33
  address(0)
41
34
  );
42
35
 
43
36
  // should work with exact fee
44
- inputsTester.newEuint256{value: FEE}(
45
- fakePrepareEuint256Ciphertext(12),
37
+ inco.newEuint256{value: FEE}(
38
+ fakePrepareEuint256Ciphertext(12, address(0), address(this)),
46
39
  address(0)
47
40
  );
48
41
  }
49
42
 
50
43
  function testPayForNewEbool() public {
51
44
  // should work with exact fee
52
- inputsTester.newEbool{value: FEE}(
53
- fakePrepareEboolCiphertext(true),
45
+ inco.newEbool{value: FEE}(
46
+ fakePrepareEboolCiphertext(true, address(0), address(this)),
54
47
  address(0)
55
48
  );
56
49
  }
57
50
 
58
51
  function testPayForNewEaddress() public {
59
52
  // should work with exact fee
60
- inputsTester.newEaddress{value: FEE}(
61
- fakePrepareEaddressCiphertext(address(this)),
53
+ inco.newEaddress{value: FEE}(
54
+ fakePrepareEaddressCiphertext(address(0), address(0), address(this)),
62
55
  address(0)
63
56
  );
64
57
  }