@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.
- package/package.json +1 -1
- package/src/DeployUtils.sol +1 -1
- package/src/Errors.sol +1 -1
- package/src/Lib.alphanet.sol +24 -3
- package/src/Lib.demonet.sol +24 -3
- package/src/Lib.devnet.sol +24 -3
- package/src/Lib.sol +24 -3
- package/src/Lib.template.sol +97 -20
- package/src/Lib.testnet.sol +24 -3
- package/src/libs/incoLightning_alphanet_v0_297966649.sol +24 -3
- package/src/libs/incoLightning_alphanet_v1_725458969.sol +24 -3
- package/src/libs/incoLightning_demonet_v0_863421733.sol +24 -3
- package/src/libs/incoLightning_devnet_v0_340846814.sol +24 -3
- package/src/libs/incoLightning_devnet_v1_904635675.sol +24 -3
- package/src/libs/incoLightning_testnet_v0_183408998.sol +24 -3
- package/src/lightning-parts/AccessControl/test/TestAdvancedAccessControl.t.sol +1 -1
- package/src/lightning-parts/EncryptedInput.sol +52 -16
- package/src/lightning-parts/EncryptedOperations.sol +86 -90
- package/src/lightning-parts/TEELifecycle.sol +153 -66
- package/src/lightning-parts/TEELifecycle.types.sol +7 -0
- package/src/lightning-parts/interfaces/ITEELifecycle.sol +13 -2
- package/src/lightning-parts/primitives/HandleGeneration.sol +23 -57
- package/src/lightning-parts/primitives/interfaces/IHandleGeneration.sol +3 -34
- package/src/lightning-parts/test/HandleMetadata.t.sol +41 -4
- package/src/lightning-parts/test/InputsFee.t.sol +14 -21
- package/src/lightning-parts/test/TestDecryptionAttestationInSynchronousFlow.t.sol +6 -2
- package/src/shared/IOwnable.sol +10 -0
- package/src/shared/IUUPSUpgradable.sol +10 -0
- package/src/shared/JsonUtils.sol +16 -0
- package/src/shared/TestUtils.sol +50 -0
- package/src/shared/TypeUtils.sol +12 -0
- package/src/test/FakeIncoInfra/FakeComputeServer.sol +1 -1
- package/src/test/FakeIncoInfra/FakeDecryptionAttester.sol +36 -34
- package/src/test/FakeIncoInfra/FakeIncoInfraBase.sol +33 -18
- package/src/test/FakeIncoInfra/KVStore.sol +1 -1
- package/src/test/FakeIncoInfra/MockOpHandler.sol +5 -5
- package/src/test/FakeIncoInfra/MockRemoteAttestation.sol +1 -1
- package/src/test/IncoTest.sol +1 -1
- package/src/test/TEELifecycle/TEELifecycleMockTest.t.sol +73 -20
- package/src/test/TestAddTwo.t.sol +1 -1
- package/src/test/TestFakeInfra.t.sol +13 -3
- package/src/version/Version.sol +4 -0
- 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
|
-
|
|
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(
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
134
|
+
_quoteVerifier.pccsRouter().fmspcTcbDaoAddr()
|
|
108
135
|
);
|
|
109
136
|
fmspcTcbDao.upsertFmspcTcb(tcbInfo);
|
|
110
137
|
IAutomataEnclaveIdentityDao enclaveIdDao = IAutomataEnclaveIdentityDao(
|
|
111
|
-
|
|
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(
|
|
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
|
-
|
|
196
|
-
|
|
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(
|
|
200
|
-
|
|
201
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
}
|
|
@@ -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
|
-
|
|
21
|
-
|
|
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
|
-
)
|
|
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
|
-
|
|
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
|
-
|
|
63
|
-
bytes32 rhs
|
|
75
|
+
bytes memory packedInputs
|
|
64
76
|
) public pure returns (bytes32 generatedHandle) {
|
|
65
|
-
generatedHandle =
|
|
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
|
-
|
|
9
|
-
|
|
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 "
|
|
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
|
-
|
|
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}(
|
|
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}(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|