@inco/lightning 0.9.0-devnet-test-10 → 0.10.0-devnet-1

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 (89) hide show
  1. package/manifest.yaml +150 -0
  2. package/package.json +8 -8
  3. package/src/CreateXHelper.sol +1 -1
  4. package/src/DeployUtils.sol +22 -28
  5. package/src/IncoLightning.sol +27 -18
  6. package/src/IncoVerifier.sol +1 -1
  7. package/src/Lib.alphanet.sol +294 -13
  8. package/src/Lib.demonet.sol +294 -13
  9. package/src/Lib.devnet.sol +294 -13
  10. package/src/Lib.sol +294 -13
  11. package/src/Lib.template.sol +357 -13
  12. package/src/Lib.testnet.sol +294 -13
  13. package/src/Types.sol +44 -0
  14. package/src/interfaces/IIncoLightning.sol +8 -12
  15. package/src/interfaces/automata-interfaces/BELE.sol +1 -1
  16. package/src/interfaces/automata-interfaces/IPCCSRouter.sol +1 -1
  17. package/src/interfaces/automata-interfaces/IPcsDao.sol +1 -1
  18. package/src/interfaces/automata-interfaces/IQuoteVerifier.sol +1 -1
  19. package/src/interfaces/automata-interfaces/Types.sol +1 -1
  20. package/src/libs/incoLightning_alphanet_v0_297966649.sol +294 -13
  21. package/src/libs/incoLightning_alphanet_v1_725458969.sol +294 -13
  22. package/src/libs/incoLightning_alphanet_v2_976644394.sol +294 -13
  23. package/src/libs/incoLightning_demonet_v0_863421733.sol +294 -13
  24. package/src/libs/incoLightning_demonet_v2_467437523.sol +294 -13
  25. package/src/libs/incoLightning_devnet_v0_340846814.sol +294 -13
  26. package/src/libs/incoLightning_devnet_v10_266391127.sol +1223 -0
  27. package/src/libs/incoLightning_devnet_v1_904635675.sol +294 -13
  28. package/src/libs/incoLightning_devnet_v2_295237520.sol +294 -13
  29. package/src/libs/incoLightning_devnet_v3_976859633.sol +294 -13
  30. package/src/libs/incoLightning_devnet_v4_409204766.sol +294 -13
  31. package/src/libs/incoLightning_devnet_v5_203964628.sol +1223 -0
  32. package/src/libs/incoLightning_devnet_v6_281949651.sol +1223 -0
  33. package/src/libs/incoLightning_devnet_v7_24560427.sol +1223 -0
  34. package/src/libs/incoLightning_devnet_v8_985328058.sol +1223 -0
  35. package/src/libs/incoLightning_devnet_v9_269218568.sol +1223 -0
  36. package/src/libs/incoLightning_testnet_v0_183408998.sol +294 -13
  37. package/src/libs/incoLightning_testnet_v2_889158349.sol +294 -13
  38. package/src/lightning-parts/AccessControl/AdvancedAccessControl.sol +8 -3
  39. package/src/lightning-parts/AccessControl/BaseAccessControlList.sol +0 -16
  40. package/src/lightning-parts/AccessControl/interfaces/IAdvancedAccessControl.sol +1 -1
  41. package/src/lightning-parts/AccessControl/interfaces/IBaseAccessControlList.sol +3 -2
  42. package/src/lightning-parts/AccessControl/test/TestAdvancedAccessControl.t.sol +18 -1
  43. package/src/lightning-parts/AccessControl/test/TestBaseAccessControl.t.sol +0 -43
  44. package/src/lightning-parts/DecryptionAttester.sol +124 -2
  45. package/src/lightning-parts/DecryptionAttester.types.sol +20 -0
  46. package/src/lightning-parts/EList.sol +397 -0
  47. package/src/lightning-parts/EncryptedInput.sol +78 -8
  48. package/src/lightning-parts/EncryptedOperations.sol +40 -34
  49. package/src/lightning-parts/Fee.sol +29 -0
  50. package/src/lightning-parts/TEELifecycle.sol +38 -30
  51. package/src/lightning-parts/TEELifecycle.types.sol +1 -1
  52. package/src/lightning-parts/TrivialEncryption.sol +1 -2
  53. package/src/lightning-parts/interfaces/IDecryptionAttester.sol +16 -1
  54. package/src/lightning-parts/interfaces/IEList.sol +38 -0
  55. package/src/lightning-parts/interfaces/IEncryptedInput.sol +9 -1
  56. package/src/lightning-parts/interfaces/IEncryptedOperations.sol +3 -2
  57. package/src/lightning-parts/interfaces/ITEELifecycle.sol +1 -1
  58. package/src/lightning-parts/interfaces/ITrivialEncryption.sol +3 -1
  59. package/src/lightning-parts/primitives/EListHandleGeneration.sol +66 -0
  60. package/src/lightning-parts/primitives/EListHandleMetadata.sol +67 -0
  61. package/src/lightning-parts/primitives/HandleGeneration.sol +31 -8
  62. package/src/lightning-parts/primitives/HandleMetadata.sol +10 -3
  63. package/src/lightning-parts/primitives/interfaces/IEListHandleMetadata.sol +8 -0
  64. package/src/lightning-parts/primitives/test/SignatureVerifier.t.sol +1 -1
  65. package/src/lightning-parts/test/Elist.t.sol +218 -0
  66. package/src/lightning-parts/test/HandleMetadata.t.sol +66 -23
  67. package/src/lightning-parts/test/TestDecryptionAttestationInSynchronousFlow.t.sol +41 -13
  68. package/src/misc/ABIHelper.sol +15 -0
  69. package/src/pasted-dependencies/ICreateX.sol +1 -1
  70. package/src/periphery/IncoUtils.sol +1 -1
  71. package/src/periphery/SessionVerifier.sol +4 -4
  72. package/src/shared/IOwnable.sol +1 -1
  73. package/src/shared/IUUPSUpgradable.sol +1 -1
  74. package/src/shared/TestUtils.sol +8 -1
  75. package/src/test/EListTester.sol +171 -0
  76. package/src/test/FakeIncoInfra/FakeComputeServer.sol +2 -2
  77. package/src/test/FakeIncoInfra/FakeIncoInfraBase.sol +3 -3
  78. package/src/test/FakeIncoInfra/MockOpHandler.sol +7 -9
  79. package/src/test/FakeIncoInfra/MockRemoteAttestation.sol +2 -1
  80. package/src/test/FakeIncoInfra/getOpForSelector.sol +0 -2
  81. package/src/test/IncoTest.sol +17 -5
  82. package/src/test/OpsTest.sol +3 -2
  83. package/src/test/TEELifecycle/TEELifecycleMockTest.t.sol +85 -57
  84. package/src/test/TestDeploy.t.sol +73 -1
  85. package/src/test/TestFakeInfra.t.sol +32 -6
  86. package/src/test/TestLib.t.sol +986 -19
  87. package/src/test/TestReceive.t.sol +42 -0
  88. package/src/test/TestUpgrade.t.sol +34 -63
  89. package/src/version/IncoLightningConfig.sol +1 -1
@@ -24,15 +24,67 @@ error ExternalHandleDoesNotMatchComputedHandle(
24
24
  address aclAddress,
25
25
  address userAddress,
26
26
  address contractAddress,
27
- int32 version
27
+ uint16 version
28
28
  );
29
29
 
30
+ /// @title EncryptedInputStorage
31
+ /// @notice Storage for EncryptedInput contract using ERC-7201 namespaced storage pattern
32
+ /// @dev Stores a whitelist of accepted versions for encrypted inputs.
33
+ abstract contract EncryptedInputStorage {
34
+
35
+ /// @notice Storage for version whitelist, using ERC-7201 namespaced storage.
36
+ struct StorageForEncryptedInput {
37
+ /// @notice Mapping of accepted version numbers for encrypted inputs.
38
+ /// @dev Only versions in this mapping are accepted for new inputs.
39
+ mapping(uint16 => bool) acceptedVersions;
40
+ }
41
+
42
+ /// @notice Storage slot location using keccak256 of a unique namespace string
43
+ bytes32 private constant ENCRYPTED_INPUT_STORAGE_LOCATION = keccak256("inco.storage.EncryptedInput");
44
+
45
+ /// @notice Retrieves the storage struct from its dedicated slot
46
+ /// @dev Uses assembly to directly access the storage slot for gas efficiency
47
+ /// @return $ Reference to the StorageForEncryptedInput struct
48
+ function _getEncryptedInputStorage() internal pure returns (StorageForEncryptedInput storage $) {
49
+ bytes32 loc = ENCRYPTED_INPUT_STORAGE_LOCATION;
50
+ assembly {
51
+ $.slot := loc
52
+ }
53
+ }
54
+
55
+ }
56
+
30
57
  /// @title EncryptedInput
31
58
  /// @notice Handles the submission of client-encrypted values to create on-chain encrypted handles.
32
59
  /// @dev Users encrypt values client-side and submit them with a prepended handle as a checksum.
33
60
  /// The contract verifies the handle matches the on-chain computation to ensure context consistency.
34
61
  /// This is a paid operation - users must send ETH to cover processing costs.
35
- abstract contract EncryptedInput is IEncryptedInput, BaseAccessControlList, HandleGeneration, Fee {
62
+ abstract contract EncryptedInput is
63
+ IEncryptedInput,
64
+ EncryptedInputStorage,
65
+ BaseAccessControlList,
66
+ HandleGeneration,
67
+ Fee
68
+ {
69
+
70
+ /// @notice Sets whether a version is accepted.
71
+ /// @param version The version number (must be non-negative).
72
+ /// @param accepted Whether the version should be accepted.
73
+ function _setAcceptedVersion(uint16 version, bool accepted) internal {
74
+ _getEncryptedInputStorage().acceptedVersions[version] = accepted;
75
+ if (accepted) {
76
+ emit VersionAccepted(version);
77
+ } else {
78
+ emit VersionRemoved(version);
79
+ }
80
+ }
81
+
82
+ /// @notice Checks whether a version is accepted.
83
+ /// @param version The version number to check.
84
+ /// @return True if the version is in the whitelist.
85
+ function isAcceptedVersion(uint16 version) public view returns (bool) {
86
+ return _getEncryptedInputStorage().acceptedVersions[version];
87
+ }
36
88
 
37
89
  /// @notice Emitted when a new encrypted input is submitted.
38
90
  /// @param result The generated handle for the encrypted value.
@@ -44,7 +96,7 @@ abstract contract EncryptedInput is IEncryptedInput, BaseAccessControlList, Hand
44
96
  bytes32 indexed result,
45
97
  address indexed contractAddress,
46
98
  address indexed user,
47
- int32 version,
99
+ uint16 version,
48
100
  bytes ciphertext,
49
101
  uint256 eventId
50
102
  );
@@ -86,6 +138,9 @@ abstract contract EncryptedInput is IEncryptedInput, BaseAccessControlList, Hand
86
138
  returns (bytes32 newHandle)
87
139
  {
88
140
  newHandle = _newInput(input, user, inputType);
141
+ // We allow to user since this is harmless and it is convenient to use the allow mapping to track inputs.
142
+ // NOTE: the allow must come after emitting the new input event, since allow emits its own event.
143
+ allowInternal(newHandle, user);
89
144
  }
90
145
 
91
146
  /// @dev Internal function to process encrypted input without fee payment.
@@ -96,6 +151,21 @@ abstract contract EncryptedInput is IEncryptedInput, BaseAccessControlList, Hand
96
151
  function newInputNotPaying(bytes calldata input, address user, ETypes inputType)
97
152
  internal
98
153
  returns (bytes32 newHandle)
154
+ {
155
+ newHandle = _newInput(input, user, inputType);
156
+ // We allow to user since this is harmless and it is convenient to use the allow mapping to track inputs.
157
+ // NOTE: the allow must come after emitting the new input event, since allow emits its own event.
158
+ allowInternal(newHandle, user);
159
+ }
160
+
161
+ /// @dev Internal function to process encrypted input without fee payment and without emitting events.
162
+ /// Used by EList for importing multiple inputs without emitting individual events for each input.
163
+ /// @param user The user address that encrypted the value.
164
+ /// @param inputType The type of encrypted value.
165
+ /// @return newHandle The generated handle.
166
+ function newInputNotPayingNotEmitting(bytes calldata input, address user, ETypes inputType)
167
+ internal
168
+ returns (bytes32 newHandle)
99
169
  {
100
170
  newHandle = _newInput(input, user, inputType);
101
171
  }
@@ -111,10 +181,13 @@ abstract contract EncryptedInput is IEncryptedInput, BaseAccessControlList, Hand
111
181
  function _newInput(bytes calldata input, address user, ETypes inputType) private returns (bytes32 handle) {
112
182
  // Since there is no sensible way to handle abi.decode errors (https://github.com/argotorg/solidity/issues/10381)
113
183
  // at least fail early on a conservative minimum length
114
- require(input.length >= 68, "Input too short, should be at least 68 bytes");
184
+ require(input.length >= 68, InputLengthTooShort(input.length));
115
185
  // Parse the version from the first 4 bytes.
116
186
  bytes4 prefix = bytes4(input[:4]);
117
- int32 version = int32(uint32(prefix));
187
+ uint16 version = uint16(uint32(prefix));
188
+
189
+ // Reject versions not in the whitelist
190
+ require(isAcceptedVersion(version), InvalidInputVersion(version));
118
191
  // Remove external handle prepended to input as a checksum
119
192
  (bytes32 externalHandle, bytes memory ciphertext) = abi.decode(input[4:], (bytes32, bytes));
120
193
  handle = getInputHandle(ciphertext, user, msg.sender, version, inputType);
@@ -143,9 +216,6 @@ abstract contract EncryptedInput is IEncryptedInput, BaseAccessControlList, Hand
143
216
  eventId: id
144
217
  });
145
218
  setDigest(abi.encodePacked(handle, id));
146
- // We allow to user since this is harmless and it is convenient to use the allow mapping to track inputs.
147
- // NOTE: the allow must come after emitting the new input event, since allow emits its own event.
148
- allowInternal(handle, user);
149
219
  allowTransientInternal(handle, msg.sender);
150
220
  }
151
221
 
@@ -1,7 +1,16 @@
1
1
  // SPDX-License-Identifier: No License
2
2
  pragma solidity ^0.8;
3
3
 
4
- import {euint256, ebool, EOps, SenderNotAllowedForHandle, ETypes, isTypeSupported, typeToBitMask} from "../Types.sol";
4
+ import {
5
+ euint256,
6
+ ebool,
7
+ EOps,
8
+ SenderNotAllowedForHandle,
9
+ ETypes,
10
+ isTypeSupported,
11
+ canCastTo,
12
+ typeToBitMask
13
+ } from "../Types.sol";
5
14
  import {BaseAccessControlList} from "./AccessControl/BaseAccessControlList.sol";
6
15
  import {HandleGeneration} from "./primitives/HandleGeneration.sol";
7
16
  import {IEncryptedOperations} from "./interfaces/IEncryptedOperations.sol";
@@ -24,6 +33,10 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
24
33
  /// @param actual The unsupported type.
25
34
  error UnsupportedType(ETypes actual);
26
35
 
36
+ /// @notice Thrown when a cast is attempted to the same type.
37
+ /// @param t The type that was both source and target.
38
+ error SameTypeCast(ETypes t);
39
+
27
40
  uint256 internal randCounter;
28
41
  uint256 internal constant ONE = 1;
29
42
 
@@ -53,7 +66,6 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
53
66
  event ELt(euint256 indexed lhs, euint256 indexed rhs, ebool indexed result, uint256 eventId);
54
67
  event EMin(euint256 indexed lhs, euint256 indexed rhs, euint256 indexed result, uint256 eventId);
55
68
  event EMax(euint256 indexed lhs, euint256 indexed rhs, euint256 indexed result, uint256 eventId);
56
- event ERand(uint256 indexed counter, ETypes randType, bytes32 indexed result, uint256 eventId);
57
69
  event ERandBounded(
58
70
  uint256 indexed counter, ETypes randType, bytes32 indexed upperBound, bytes32 indexed result, uint256 eventId
59
71
  );
@@ -135,7 +147,7 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
135
147
  }
136
148
 
137
149
  /// @notice Divides one encrypted uint256 by another.
138
- /// @dev Division by zero returns zero.
150
+ /// @dev Division by zero returns encrypted type(uint256).max.
139
151
  /// @param lhs The dividend (encrypted).
140
152
  /// @param rhs The divisor (encrypted).
141
153
  /// @return result The encrypted quotient (lhs / rhs).
@@ -149,7 +161,7 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
149
161
  }
150
162
 
151
163
  /// @notice Computes the remainder of dividing one encrypted uint256 by another.
152
- /// @dev Remainder by zero returns zero.
164
+ /// @dev Remainder by zero returns the encrypted dividend (lhs).
153
165
  /// @param lhs The dividend (encrypted).
154
166
  /// @param rhs The divisor (encrypted).
155
167
  /// @return result The encrypted remainder (lhs % rhs).
@@ -167,11 +179,11 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
167
179
  /// @param rhs The right-hand side encrypted operand (must be same type as lhs).
168
180
  /// @return result The encrypted bitwise AND result.
169
181
  function eBitAnd(bytes32 lhs, bytes32 rhs) external returns (bytes32 result) {
182
+ checkInput(lhs, SUPPORTED_TYPES_MASK);
183
+ checkInput(rhs, SUPPORTED_TYPES_MASK);
170
184
  ETypes lhsType = typeOf(lhs);
171
185
  ETypes rhsType = typeOf(rhs);
172
- checkInput(lhs, typeToBitMask(lhsType));
173
- checkInput(rhs, typeToBitMask(rhsType));
174
- require(lhsType == rhsType, UnexpectedType(lhsType, typeToBitMask(rhsType)));
186
+ require(lhsType == rhsType, UnexpectedType(rhsType, typeToBitMask(lhsType)));
175
187
  uint256 id = getNextEventId();
176
188
  result = createResultHandle(EOps.BitAnd, lhsType, abi.encodePacked(lhs, rhs));
177
189
  emit EBitAnd(lhs, rhs, result, id);
@@ -183,11 +195,11 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
183
195
  /// @param rhs The right-hand side encrypted operand (must be same type as lhs).
184
196
  /// @return result The encrypted bitwise OR result.
185
197
  function eBitOr(bytes32 lhs, bytes32 rhs) external returns (bytes32 result) {
198
+ checkInput(lhs, SUPPORTED_TYPES_MASK);
199
+ checkInput(rhs, SUPPORTED_TYPES_MASK);
186
200
  ETypes lhsType = typeOf(lhs);
187
201
  ETypes rhsType = typeOf(rhs);
188
- checkInput(lhs, typeToBitMask(lhsType));
189
- checkInput(rhs, typeToBitMask(rhsType));
190
- require(lhsType == rhsType, UnexpectedType(lhsType, typeToBitMask(rhsType)));
202
+ require(lhsType == rhsType, UnexpectedType(rhsType, typeToBitMask(lhsType)));
191
203
  uint256 id = getNextEventId();
192
204
  result = createResultHandle(EOps.BitOr, lhsType, abi.encodePacked(lhs, rhs));
193
205
  emit EBitOr(lhs, rhs, result, id);
@@ -199,11 +211,11 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
199
211
  /// @param rhs The right-hand side encrypted operand (must be same type as lhs).
200
212
  /// @return result The encrypted bitwise XOR result.
201
213
  function eBitXor(bytes32 lhs, bytes32 rhs) external returns (bytes32 result) {
214
+ checkInput(lhs, SUPPORTED_TYPES_MASK);
215
+ checkInput(rhs, SUPPORTED_TYPES_MASK);
202
216
  ETypes lhsType = typeOf(lhs);
203
217
  ETypes rhsType = typeOf(rhs);
204
- checkInput(lhs, typeToBitMask(lhsType));
205
- checkInput(rhs, typeToBitMask(rhsType));
206
- require(lhsType == rhsType, UnexpectedType(lhsType, typeToBitMask(rhsType)));
218
+ require(lhsType == rhsType, UnexpectedType(rhsType, typeToBitMask(lhsType)));
207
219
  uint256 id = getNextEventId();
208
220
  result = createResultHandle(EOps.BitXor, lhsType, abi.encodePacked(lhs, rhs));
209
221
  emit EBitXor(lhs, rhs, result, id);
@@ -270,6 +282,9 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
270
282
  function eEq(bytes32 lhs, bytes32 rhs) external returns (ebool result) {
271
283
  checkInput(lhs, SUPPORTED_TYPES_MASK);
272
284
  checkInput(rhs, SUPPORTED_TYPES_MASK);
285
+ ETypes lhsType = typeOf(lhs);
286
+ ETypes rhsType = typeOf(rhs);
287
+ require(lhsType == rhsType, UnexpectedType(rhsType, typeToBitMask(lhsType)));
273
288
 
274
289
  result = ebool.wrap(createResultHandle(EOps.Eq, ETypes.Bool, abi.encodePacked(lhs, rhs)));
275
290
  uint256 id = getNextEventId();
@@ -285,6 +300,9 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
285
300
  function eNe(bytes32 lhs, bytes32 rhs) external returns (ebool result) {
286
301
  checkInput(lhs, SUPPORTED_TYPES_MASK);
287
302
  checkInput(rhs, SUPPORTED_TYPES_MASK);
303
+ ETypes lhsType = typeOf(lhs);
304
+ ETypes rhsType = typeOf(rhs);
305
+ require(lhsType == rhsType, UnexpectedType(rhsType, typeToBitMask(lhsType)));
288
306
 
289
307
  result = ebool.wrap(createResultHandle(EOps.Ne, ETypes.Bool, abi.encodePacked(lhs, rhs)));
290
308
  uint256 id = getNextEventId();
@@ -381,42 +399,31 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
381
399
  setDigest(abi.encodePacked(result, id));
382
400
  }
383
401
 
384
- /// @notice Casts an encrypted value to a different encrypted type.
385
- /// @dev Supports casting between euint256, ebool, and eaddress.
402
+ /// @notice Casts an encrypted value to a different encrypted type. Same-type casting is not allowed.
403
+ /// @dev Supports casting to euint256 and eaddress. Casting to ebool is not supported, only from ebool to a larger type.
404
+ /// Reverts with SameTypeCast if the source type matches the target type.
386
405
  /// @param ct The encrypted value to cast.
387
406
  /// @param toType The target type to cast to.
388
407
  /// @return result The casted encrypted value.
389
408
  function eCast(bytes32 ct, ETypes toType) external returns (bytes32 result) {
390
409
  checkInput(ct, SUPPORTED_TYPES_MASK);
391
- require(isTypeSupported(toType), UnsupportedType(toType));
410
+ require(canCastTo(toType), UnsupportedType(toType));
411
+ require(typeOf(ct) != toType, SameTypeCast(toType));
392
412
  result = createResultHandle(EOps.Cast, toType, abi.encodePacked(ct));
393
- allowTransientInternal(result, msg.sender);
394
413
  uint256 id = getNextEventId();
395
414
  emit ECast(ct, uint8(toType), result, id);
396
415
  setDigest(abi.encodePacked(result, id));
397
416
  }
398
417
 
399
- /// @notice Generates an encrypted random value of the specified type.
400
- /// @dev This is a paid operation.
401
- /// @param randType The type of random value to generate.
402
- /// @return result An encrypted random value.
403
- function eRand(ETypes randType) external payable paying returns (bytes32 result) {
404
- require(isTypeSupported(randType), UnsupportedType(randType));
405
- randCounter++;
406
- result = createResultHandle(EOps.Rand, randType, abi.encodePacked(bytes32(randCounter)));
407
- uint256 id = getNextEventId();
408
- emit ERand(randCounter, randType, result, id);
409
- setDigest(abi.encodePacked(result, id));
410
- }
411
-
412
418
  /// @notice Generates an encrypted random value bounded by an upper limit.
413
419
  /// @dev This is a paid operation. The result is in the range [0, upperBound).
414
- /// @param upperBound The encrypted upper bound (exclusive).
415
- /// @param randType The type of random value to generate.
420
+ /// @param upperBound The encrypted upper bound (exclusive). If the upper bound is e(0), the whole bit width of randType is sampled.
421
+ /// @param randType The type of random value to generate. If upperBound is larger than the maximum value of randType, the function will revert.
416
422
  /// @return result An encrypted random value less than upperBound.
417
423
  function eRandBounded(bytes32 upperBound, ETypes randType) external payable paying returns (bytes32 result) {
418
424
  require(isTypeSupported(randType), UnsupportedType(randType));
419
- checkInput(upperBound, typeToBitMask(ETypes.Uint256));
425
+ require(typeOf(upperBound) <= randType, UnexpectedType(typeOf(upperBound), typeToBitMask(randType)));
426
+ checkInput(upperBound, SUPPORTED_TYPES_MASK);
420
427
  randCounter++;
421
428
  result = createResultHandle(EOps.RandBounded, randType, abi.encodePacked(bytes32(randCounter), upperBound));
422
429
  uint256 id = getNextEventId();
@@ -435,7 +442,6 @@ abstract contract EncryptedOperations is IEncryptedOperations, BaseAccessControl
435
442
  ETypes returnType = checkEIfThenElseInputs(control, ifTrue, ifFalse);
436
443
  result =
437
444
  createResultHandle(EOps.IfThenElse, returnType, abi.encodePacked(ebool.unwrap(control), ifTrue, ifFalse));
438
- allowTransientInternal(result, msg.sender);
439
445
  uint256 id = getNextEventId();
440
446
  emit EIfThenElse(control, ifTrue, ifFalse, result, id);
441
447
  setDigest(abi.encodePacked(result, id));
@@ -1,11 +1,15 @@
1
1
  // SPDX-License-Identifier: No License
2
2
  pragma solidity ^0.8;
3
3
 
4
+ import {ETypes, typeBitSize} from "../Types.sol";
5
+
4
6
  /// @dev The current fee required for paid encryption operations.
5
7
  /// This constant may be modified through contract upgrades.
6
8
  /// Developers should call getFee() rather than hardcoding this value.
7
9
  uint256 constant FEE = 0.000001 ether;
8
10
 
11
+ uint256 constant BIT_FEE = FEE / 256;
12
+
9
13
  /// @title Fee
10
14
  /// @notice Fee management utilities for encryption operations that require payment
11
15
  /// @dev Certain operations (encrypted inputs, randomness) require a fee to cover covalidator costs.
@@ -48,6 +52,31 @@ abstract contract Fee {
48
52
  _;
49
53
  }
50
54
 
55
+ /// @notice Modifier that requires payment proportional to elist bit size
56
+ /// @dev Fee = totalBits * BIT_FEE. totalBits is the sum of bit sizes across all elist inputs and outputs.
57
+ /// @param totalBits The total elist bit count for the operation
58
+ modifier payingElistFee(uint256 totalBits) {
59
+ require(msg.value == totalBits * BIT_FEE, FeeNotPaid());
60
+ _;
61
+ }
62
+
63
+ /// @notice Returns the per-bit fee for elist operations
64
+ /// @dev The fee may change through contract upgrades. Always query this function
65
+ /// to get the current fee rather than caching the value.
66
+ /// @return The per-bit fee amount in wei
67
+ function getBitFee() public pure returns (uint256) {
68
+ return BIT_FEE;
69
+ }
70
+
71
+ /// @notice Returns the fee for an elist operation given element count and type
72
+ /// @dev Fee = BIT_FEE * nOfElements * typeBitSize(elType)
73
+ /// @param nOfElements The number of elements in the resulting list
74
+ /// @param elType The element type of the list
75
+ /// @return The fee amount in wei
76
+ function getEListFee(uint16 nOfElements, ETypes elType) public pure returns (uint256) {
77
+ return BIT_FEE * uint256(nOfElements) * typeBitSize(elType);
78
+ }
79
+
51
80
  /// @notice Withdraws all accumulated fees to the specified recipient
52
81
  /// @dev Internal function called by IncoLightning.withdrawFees(). Transfers the entire
53
82
  /// contract balance to the recipient.
@@ -1,4 +1,4 @@
1
- pragma solidity ^0.8.19;
1
+ pragma solidity ^0.8;
2
2
 
3
3
  import {BootstrapResult, UpgradeResult, AddNodeResult} from "./TEELifecycle.types.sol";
4
4
  import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
@@ -23,8 +23,6 @@ contract TEELifecycleStorage {
23
23
 
24
24
  struct StorageForTeeLifecycle {
25
25
  IQuoteVerifier quoteVerifier;
26
- BootstrapResult verifiedBootstrapResult;
27
- bool bootstrapComplete;
28
26
  // @notice The list of approved TEE versions, each item is the MR_AGGREGATED 32 bytes
29
27
  // @dev The index of the TEE version is the version number
30
28
  bytes32[] approvedTeeVersions;
@@ -70,8 +68,6 @@ abstract contract TEELifecycle is
70
68
  // Events
71
69
  // @notice A new MR_AGGREGATED has been approved
72
70
  event NewTEEVersionApproved(uint256 indexed version, bytes32 indexed mrAggregated);
73
- // @notice A previously approved TEE version has been removed
74
- event TEEVersionRemoved(bytes32 indexed mrAggregated);
75
71
  event NewCovalidatorAdded(address covalidatorAddress, bytes quote);
76
72
  event BootstrapStageComplete(address indexed newEoaSigner, BootstrapResult bootstrapResult);
77
73
  // @notice Emitted to prove that an EOA has upgraded their TDX to a new
@@ -159,7 +155,7 @@ abstract contract TEELifecycle is
159
155
  UpgradeResult calldata upgradeResult,
160
156
  bytes calldata quote,
161
157
  bytes calldata signature
162
- ) public {
158
+ ) public onlyOwner {
163
159
  StorageForTeeLifecycle storage $ = getTeeLifecycleStorage();
164
160
 
165
161
  require(isBootstrapComplete(), BootstrapNotComplete());
@@ -213,28 +209,6 @@ abstract contract TEELifecycle is
213
209
  emit NewTEEVersionApproved($.approvedTeeVersions.length - 1, newMrAggregated);
214
210
  }
215
211
 
216
- /**
217
- * @notice Removes a previously approved TEE version from the contract state
218
- * @param mrAggregated - The MR_AGGREGATED bytes of the TEE version to remove
219
- */
220
- function removeApprovedTeeVersion(bytes32 mrAggregated) public onlyOwner {
221
- StorageForTeeLifecycle storage $ = getTeeLifecycleStorage();
222
- bool found = false;
223
- for (uint256 i = 0; i < $.approvedTeeVersions.length; i++) {
224
- if ($.approvedTeeVersions[i] == mrAggregated) {
225
- // Shift all elements after index i to the left to preserve insertion order
226
- for (uint256 j = i; j < $.approvedTeeVersions.length - 1; j++) {
227
- $.approvedTeeVersions[j] = $.approvedTeeVersions[j + 1];
228
- }
229
- $.approvedTeeVersions.pop();
230
- found = true;
231
- break;
232
- }
233
- }
234
- require(found, TEEVersionNotFound());
235
- emit TEEVersionRemoved(mrAggregated);
236
- }
237
-
238
212
  function _isApprovedTeeVersion(bytes32 newMrAggregated) internal view returns (bool) {
239
213
  StorageForTeeLifecycle storage $ = getTeeLifecycleStorage();
240
214
  for (uint256 i = 0; i < $.approvedTeeVersions.length; i++) {
@@ -283,6 +257,40 @@ abstract contract TEELifecycle is
283
257
  return getTeeLifecycleStorage().networkPubkey.length > 0;
284
258
  }
285
259
 
260
+ /**
261
+ * @notice Resets the contract state to the initial state.
262
+ * @dev This function performs a destructive operation and should be used carefully. In particular:
263
+ * 1) This function will remove all signers and reset the network pubkey and approved TEE versions, requiring a full bootstrap to restore normal operation.
264
+ * 2) The contract effectively enters a maintenance mode where any operations that depend on signers or the network key will fail until re-bootstrap is completed.
265
+ * 3) This function is intended to be called only as part of a coordinated key rotation or recovery process, with off-chain components updated accordingly.
266
+ * @dev This function is only callable by the owner.
267
+ */
268
+ function reset() public onlyOwner {
269
+ getTeeLifecycleStorage().networkPubkey = bytes("");
270
+ getTeeLifecycleStorage().approvedTeeVersions = new bytes32[](0);
271
+
272
+ // Directly access SignatureVerifier storage to reset signers and threshold
273
+ // We bypass the normal functions because:
274
+ // 1. removeSigner is external and has threshold validation
275
+ // 2. setThreshold requires newThreshold > 0
276
+ // We emit RemovedSignatureVerifier and ThresholdChanged so off-chain
277
+ // systems tracking signer changes via events stay in sync.
278
+ StorageForSigVerifier storage sigStorage = getSigVerifierStorage();
279
+ uint256 oldThreshold = sigStorage.threshold;
280
+ if (oldThreshold > 0) {
281
+ emit ThresholdChanged(oldThreshold, 0);
282
+ }
283
+ sigStorage.threshold = 0;
284
+ // In theory, this could revert if there are many signers. But in
285
+ // practice, this should not be a problem.
286
+ while (sigStorage.signers.length > 0) {
287
+ address signer = sigStorage.signers[sigStorage.signers.length - 1];
288
+ sigStorage.isSigner[signer] = false;
289
+ sigStorage.signers.pop();
290
+ emit RemovedSignatureVerifier(signer);
291
+ }
292
+ }
293
+
286
294
  /**
287
295
  * @notice From https://github.com/automata-network/automata-dcap-attestation/blob/evm-v1.0.0/evm/contracts/AttestationEntrypointBase.sol#L103
288
296
  * @notice full on-chain verification for an attestation
@@ -381,7 +389,7 @@ abstract contract TEELifecycle is
381
389
 
382
390
  /**
383
391
  * @notice Computes the MR_AGGREGATED from the TD10 report body. It is defined as:
384
- * KECCAK256(mrTd ++ rtMr0 ++ rtMr1 ++ rtMr2 ++ rtMr3)
392
+ * as KECCAK256(abi.encode(MRTD, RTMR0, RTMR1, RTMR2))
385
393
  * @param mrTd - The MR_TD bytes
386
394
  * @param rtMr0 - The RTMR0 bytes
387
395
  * @param rtMr1 - The RTMR1 bytes
@@ -393,7 +401,7 @@ abstract contract TEELifecycle is
393
401
  pure
394
402
  returns (bytes32)
395
403
  {
396
- bytes memory message = abi.encodePacked(mrTd, rtMr0, rtMr1, rtMr2);
404
+ bytes memory message = abi.encode(mrTd, rtMr0, rtMr1, rtMr2);
397
405
  return keccak256(message);
398
406
  }
399
407
 
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: No License
2
- pragma solidity ^0.8.19;
2
+ pragma solidity ^0.8;
3
3
 
4
4
  /**
5
5
  * @notice A struct representing what the TDX EOA signs during the bootstrap process.
@@ -1,7 +1,6 @@
1
1
  // SPDX-License-Identifier: No License
2
2
  pragma solidity ^0.8;
3
3
 
4
- import {EventCounter} from "./primitives/EventCounter.sol";
5
4
  import {euint256, ebool, eaddress, ETypes} from "../Types.sol";
6
5
  import {BaseAccessControlList} from "./AccessControl/BaseAccessControlList.sol";
7
6
  import {HandleGeneration} from "./primitives/HandleGeneration.sol";
@@ -13,7 +12,7 @@ import {ITrivialEncryption} from "./interfaces/ITrivialEncryption.sol";
13
12
  /// on-chain (emitted in events), so this should only be used for values that are already public.
14
13
  /// Common use cases include initializing encrypted state with known values or creating encrypted
15
14
  /// constants. The resulting handles are granted transient access to the caller.
16
- abstract contract TrivialEncryption is ITrivialEncryption, EventCounter, BaseAccessControlList, HandleGeneration {
15
+ abstract contract TrivialEncryption is ITrivialEncryption, BaseAccessControlList, HandleGeneration {
17
16
 
18
17
  /// @notice Emitted when a trivial encryption is performed.
19
18
  /// @param result The handle representing the encrypted value.
@@ -1,7 +1,11 @@
1
1
  // SPDX-License-Identifier: No License
2
2
  pragma solidity ^0.8;
3
3
 
4
- import {DecryptionAttestation} from "../DecryptionAttester.types.sol";
4
+ import {
5
+ DecryptionAttestation,
6
+ ElementAttestationWithProof,
7
+ ReencryptionAttestation
8
+ } from "../DecryptionAttester.types.sol";
5
9
 
6
10
  interface IDecryptionAttester {
7
11
 
@@ -10,5 +14,16 @@ interface IDecryptionAttester {
10
14
  external
11
15
  view
12
16
  returns (bool);
17
+ function isValidEListDecryptionAttestation(
18
+ bytes32 elistHandle,
19
+ ElementAttestationWithProof[] memory proofElements,
20
+ bytes32 proof,
21
+ bytes[] memory signatures
22
+ ) external view returns (bool);
23
+ function reencryptionAttestationDigest(ReencryptionAttestation memory attestation) external view returns (bytes32);
24
+ function isValidReencryptionAttestation(
25
+ ReencryptionAttestation[] calldata attestations,
26
+ bytes[] calldata signatures
27
+ ) external view returns (bool);
13
28
 
14
29
  }
@@ -0,0 +1,38 @@
1
+ /// SPDX-License-Identifier: No License
2
+ pragma solidity ^0.8;
3
+
4
+ import {elist, ETypes} from "../../Types.sol";
5
+ import {IEListHandleMetadata} from "../primitives/interfaces/IEListHandleMetadata.sol";
6
+ import {IEncryptedOperations} from "./IEncryptedOperations.sol";
7
+ import {IEncryptedInput} from "./IEncryptedInput.sol";
8
+
9
+ interface IEList is IEncryptedOperations, IEncryptedInput, IEListHandleMetadata {
10
+
11
+ function newEList(bytes32[] memory handles, ETypes listType) external payable returns (elist newList);
12
+
13
+ function newEList(bytes[] calldata inputs, ETypes listType, address user) external payable returns (elist newList);
14
+
15
+ function listAppend(elist list, bytes32 value) external payable returns (elist result);
16
+
17
+ function listGet(elist list, uint16 i) external returns (bytes32 result);
18
+
19
+ function listGetOr(elist list, bytes32 i, bytes32 defaultValue) external returns (bytes32 result);
20
+
21
+ function listSet(elist list, bytes32 i, bytes32 value) external payable returns (elist result);
22
+
23
+ function listInsert(elist list, bytes32 i, bytes32 value) external payable returns (elist result);
24
+
25
+ function listConcat(elist lhs, elist rhs) external payable returns (elist result);
26
+
27
+ function listSlice(elist list, bytes32 start, uint16 len, bytes32 defaultValue)
28
+ external
29
+ payable
30
+ returns (elist result);
31
+
32
+ function listRange(uint16 start, uint16 end, ETypes listType) external payable returns (elist result);
33
+
34
+ function listShuffle(elist list) external payable returns (elist result);
35
+
36
+ function listReverse(elist list) external payable returns (elist result);
37
+
38
+ }
@@ -2,8 +2,16 @@
2
2
  pragma solidity ^0.8;
3
3
 
4
4
  import {euint256, ebool, eaddress} from "../../Types.sol";
5
+ import {IBaseAccessControlList} from "../AccessControl/interfaces/IBaseAccessControlList.sol";
6
+ import {IHandleGeneration} from "../primitives/interfaces/IHandleGeneration.sol";
5
7
 
6
- interface IEncryptedInput {
8
+ interface IEncryptedInput is IBaseAccessControlList, IHandleGeneration {
9
+
10
+ error InvalidInputVersion(uint16 version);
11
+ error InputLengthTooShort(uint256 length);
12
+
13
+ event VersionAccepted(uint16 indexed version);
14
+ event VersionRemoved(uint16 indexed version);
7
15
 
8
16
  function newEuint256(bytes calldata ciphertext, address user) external payable returns (euint256 newValue);
9
17
  function newEbool(bytes calldata ciphertext, address user) external payable returns (ebool newValue);
@@ -2,8 +2,10 @@
2
2
  pragma solidity ^0.8;
3
3
 
4
4
  import {euint256, ebool, ETypes} from "../../Types.sol";
5
+ import {IBaseAccessControlList} from "../AccessControl/interfaces/IBaseAccessControlList.sol";
6
+ import {IHandleGeneration} from "../primitives/interfaces/IHandleGeneration.sol";
5
7
 
6
- interface IEncryptedOperations {
8
+ interface IEncryptedOperations is IBaseAccessControlList, IHandleGeneration {
7
9
 
8
10
  function eAdd(euint256 lhs, euint256 rhs) external returns (euint256 result);
9
11
  function eSub(euint256 lhs, euint256 rhs) external returns (euint256 result);
@@ -27,7 +29,6 @@ interface IEncryptedOperations {
27
29
  function eMax(euint256 lhs, euint256 rhs) external returns (euint256 result);
28
30
  function eNot(ebool operand) external returns (ebool result);
29
31
  function eCast(bytes32 ct, ETypes toType) external returns (bytes32 result);
30
- function eRand(ETypes randType) external payable returns (bytes32 result);
31
32
  function eRandBounded(bytes32 upperBound, ETypes randType) external payable returns (bytes32 result);
32
33
  function eIfThenElse(ebool condition, bytes32 ifTrue, bytes32 ifFalse) external returns (bytes32 result);
33
34
 
@@ -1,5 +1,5 @@
1
1
  /// SPDX-License-Identifier: No License
2
- pragma solidity ^0.8.19;
2
+ pragma solidity ^0.8;
3
3
 
4
4
  import {BootstrapResult, UpgradeResult, AddNodeResult} from "../TEELifecycle.types.sol";
5
5
  import {IQuoteVerifier} from "../../interfaces/automata-interfaces/IQuoteVerifier.sol";
@@ -2,8 +2,10 @@
2
2
  pragma solidity ^0.8;
3
3
 
4
4
  import {euint256, ebool, eaddress} from "../../Types.sol";
5
+ import {IBaseAccessControlList} from "../AccessControl/interfaces/IBaseAccessControlList.sol";
6
+ import {IHandleGeneration} from "../primitives/interfaces/IHandleGeneration.sol";
5
7
 
6
- interface ITrivialEncryption {
8
+ interface ITrivialEncryption is IBaseAccessControlList, IHandleGeneration {
7
9
 
8
10
  function asEuint256(uint256 value) external returns (euint256 newEuint256);
9
11
  function asEbool(bool value) external returns (ebool newEbool);