@inco/lightning 0.8.0-devnet-3 → 0.8.0-devnet-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/README.md +59 -1
- package/manifest.yaml +22 -0
- package/package.json +1 -1
- package/src/DeployUtils.sol +71 -25
- package/src/IncoLightning.sol +27 -7
- package/src/IncoVerifier.sol +18 -1
- package/src/Lib.alphanet.sol +390 -3
- package/src/Lib.demonet.sol +390 -3
- package/src/Lib.devnet.sol +391 -4
- package/src/Lib.sol +391 -4
- package/src/Lib.template.sol +387 -0
- package/src/Lib.testnet.sol +390 -3
- package/src/libs/incoLightning_alphanet_v0_297966649.sol +390 -3
- package/src/libs/incoLightning_alphanet_v1_725458969.sol +390 -3
- package/src/libs/incoLightning_alphanet_v2_976644394.sol +390 -3
- package/src/libs/incoLightning_demonet_v0_863421733.sol +390 -3
- package/src/libs/incoLightning_demonet_v2_467437523.sol +390 -3
- package/src/libs/incoLightning_devnet_v0_340846814.sol +390 -3
- package/src/libs/incoLightning_devnet_v1_904635675.sol +390 -3
- package/src/libs/incoLightning_devnet_v2_295237520.sol +390 -3
- package/src/libs/incoLightning_devnet_v3_976859633.sol +390 -3
- package/src/libs/incoLightning_devnet_v4_409204766.sol +921 -0
- package/src/libs/incoLightning_testnet_v0_183408998.sol +390 -3
- package/src/libs/incoLightning_testnet_v2_889158349.sol +390 -3
- package/src/lightning-parts/AccessControl/AdvancedAccessControl.sol +65 -4
- package/src/lightning-parts/AccessControl/BaseAccessControlList.sol +71 -5
- package/src/lightning-parts/DecryptionAttester.sol +16 -3
- package/src/lightning-parts/EncryptedInput.sol +80 -17
- package/src/lightning-parts/EncryptedOperations.sol +134 -1
- package/src/lightning-parts/Fee.sol +29 -6
- package/src/lightning-parts/interfaces/IEncryptedInput.sol +3 -3
- package/src/lightning-parts/primitives/EventCounter.sol +36 -5
- package/src/lightning-parts/primitives/HandleGeneration.sol +49 -13
- package/src/lightning-parts/primitives/HandleMetadata.sol +28 -0
- package/src/lightning-parts/primitives/LightningAddressGetter.sol +10 -0
- package/src/lightning-parts/primitives/VerifierAddressGetter.sol +10 -0
- package/src/lightning-parts/primitives/test/SignatureVerifier.t.sol +0 -2
- package/src/lightning-parts/test/HandleMetadata.t.sol +21 -13
- package/src/periphery/IncoUtils.sol +1 -0
- package/src/periphery/SessionVerifier.sol +35 -7
- package/src/test/FakeIncoInfra/FakeIncoInfraBase.sol +10 -2
- package/src/test/FakeIncoInfra/MockOpHandler.sol +1 -1
- package/src/test/TestFakeInfra.t.sol +536 -1
- package/src/version/IncoLightningConfig.sol +2 -2
- package/src/libs/incoLightning_devnet_v1_887305889.sol +0 -453
- package/src/libs/incoLightning_testnet_v1_938327937.sol +0 -453
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
// SPDX-License-Identifier: No License
|
|
2
2
|
pragma solidity ^0.8;
|
|
3
3
|
|
|
4
|
+
/// @title LightningAddressGetter
|
|
5
|
+
/// @notice Provides immutable access to the IncoLightning contract address
|
|
6
|
+
/// @dev Abstract contract that stores the main IncoLightning address at deployment time.
|
|
7
|
+
/// Used by peripheral contracts (like AdvancedAccessControl, SessionVerifier) that need
|
|
8
|
+
/// to call back to the main IncoLightning contract for ACL lookups or other operations.
|
|
9
|
+
/// The address is immutable to prevent redirection attacks.
|
|
4
10
|
abstract contract LightningAddressGetter {
|
|
5
11
|
|
|
12
|
+
/// @notice The main IncoLightning contract address
|
|
13
|
+
/// @dev Set immutably at deployment. Used for delegating calls and ACL lookups.
|
|
6
14
|
// forge-lint: disable-next-line(screaming-snake-case-immutable)
|
|
7
15
|
address internal immutable incoLightningAddress;
|
|
8
16
|
|
|
17
|
+
/// @notice Initializes the contract with the IncoLightning address
|
|
18
|
+
/// @param _incoLightningAddress The address of the deployed IncoLightning contract
|
|
9
19
|
constructor(address _incoLightningAddress) {
|
|
10
20
|
incoLightningAddress = _incoLightningAddress;
|
|
11
21
|
}
|
|
@@ -4,11 +4,21 @@ pragma solidity ^0.8;
|
|
|
4
4
|
import {IIncoVerifier} from "../../interfaces/IIncoVerifier.sol";
|
|
5
5
|
import {IVerifierAddressGetter} from "./interfaces/IVerifierAddressGetter.sol";
|
|
6
6
|
|
|
7
|
+
/// @title VerifierAddressGetter
|
|
8
|
+
/// @notice Provides immutable access to the IncoVerifier contract address
|
|
9
|
+
/// @dev Abstract contract that stores the IncoVerifier address at deployment time.
|
|
10
|
+
/// The IncoVerifier is responsible for validating decryption attestations from covalidators.
|
|
11
|
+
/// This pattern ensures the verifier address is set once and cannot be changed,
|
|
12
|
+
/// which is critical for security as the verifier is trusted for attestation validation.
|
|
7
13
|
abstract contract VerifierAddressGetter is IVerifierAddressGetter {
|
|
8
14
|
|
|
15
|
+
/// @notice The IncoVerifier contract used for attestation validation
|
|
16
|
+
/// @dev Set immutably at deployment. Used to verify decryption proofs from covalidators.
|
|
9
17
|
// forge-lint: disable-next-line(screaming-snake-case-immutable)
|
|
10
18
|
IIncoVerifier public immutable incoVerifier;
|
|
11
19
|
|
|
20
|
+
/// @notice Initializes the contract with the IncoVerifier address
|
|
21
|
+
/// @param _incoVerifier The address of the deployed IncoVerifier contract
|
|
12
22
|
constructor(address _incoVerifier) {
|
|
13
23
|
incoVerifier = IIncoVerifier(_incoVerifier);
|
|
14
24
|
}
|
|
@@ -357,7 +357,6 @@ contract TestSignatureVerifier is TestUtils, SignatureVerifier {
|
|
|
357
357
|
// Create 3 signatures: Alice, Bob (both valid), and Dave (invalid)
|
|
358
358
|
// After sorting, Dave's signature will be placed according to his address
|
|
359
359
|
// As long as the first 2 signatures checked are from valid signers, it should pass
|
|
360
|
-
bytes[] memory signatures = new bytes[](3);
|
|
361
360
|
bytes memory aliceSig = getSignatureForDigest(digest, alicePrivKey);
|
|
362
361
|
bytes memory bobSig = getSignatureForDigest(digest, bobPrivKey);
|
|
363
362
|
bytes memory daveSig = getSignatureForDigest(digest, davePrivKey);
|
|
@@ -413,7 +412,6 @@ contract TestSignatureVerifier is TestUtils, SignatureVerifier {
|
|
|
413
412
|
bytes32 digest = keccak256("test message");
|
|
414
413
|
|
|
415
414
|
// Create signatures where an invalid signer (Dave) will be in the first threshold
|
|
416
|
-
bytes[] memory signatures = new bytes[](3);
|
|
417
415
|
bytes memory aliceSig = getSignatureForDigest(digest, alicePrivKey);
|
|
418
416
|
bytes memory bobSig = getSignatureForDigest(digest, bobPrivKey);
|
|
419
417
|
bytes memory daveSig = getSignatureForDigest(digest, davePrivKey);
|
|
@@ -105,8 +105,16 @@ contract TestHandleMetadata is
|
|
|
105
105
|
{
|
|
106
106
|
// We need a single word here to get correct encoding
|
|
107
107
|
bytes memory ciphertext = abi.encode(word);
|
|
108
|
-
bytes32 handle = getInputHandle(
|
|
109
|
-
|
|
108
|
+
bytes32 handle = getInputHandle(
|
|
109
|
+
ciphertext,
|
|
110
|
+
address(this),
|
|
111
|
+
user,
|
|
112
|
+
contractAddress,
|
|
113
|
+
0,
|
|
114
|
+
/* unspecified */
|
|
115
|
+
inputType
|
|
116
|
+
);
|
|
117
|
+
input = abi.encodePacked(int32(0), abi.encode(handle, ciphertext));
|
|
110
118
|
}
|
|
111
119
|
|
|
112
120
|
// ============ Tests for HandleGeneration functions ============
|
|
@@ -143,11 +151,8 @@ contract TestHandleMetadata is
|
|
|
143
151
|
// ============ Tests for EncryptedInput internal functions ============
|
|
144
152
|
|
|
145
153
|
/// @notice Expose the internal newInputNotPaying for testing
|
|
146
|
-
function exposedNewInputNotPaying(bytes
|
|
147
|
-
|
|
148
|
-
returns (bytes32)
|
|
149
|
-
{
|
|
150
|
-
return newInputNotPaying(ciphertext, user, inputType);
|
|
154
|
+
function exposedNewInputNotPaying(bytes calldata input, address user, ETypes inputType) public returns (bytes32) {
|
|
155
|
+
return newInputNotPaying(input, user, inputType);
|
|
151
156
|
}
|
|
152
157
|
|
|
153
158
|
function testNewInputNotPaying() public {
|
|
@@ -167,9 +172,10 @@ contract TestHandleMetadata is
|
|
|
167
172
|
returns (bytes memory input)
|
|
168
173
|
{
|
|
169
174
|
bytes memory ciphertext = abi.encode(word);
|
|
175
|
+
int32 version = 0; // unspecified
|
|
170
176
|
// For external calls via this., msg.sender is address(this)
|
|
171
|
-
bytes32 handle = getInputHandle(ciphertext, address(this), user, address(this), inputType);
|
|
172
|
-
input = abi.encode(handle, ciphertext);
|
|
177
|
+
bytes32 handle = getInputHandle(ciphertext, address(this), user, address(this), version, inputType);
|
|
178
|
+
input = abi.encodePacked(version, abi.encode(handle, ciphertext));
|
|
173
179
|
}
|
|
174
180
|
|
|
175
181
|
// ============ Tests for EncryptedInput error branches ============
|
|
@@ -178,7 +184,7 @@ contract TestHandleMetadata is
|
|
|
178
184
|
address self = address(this);
|
|
179
185
|
// Input less than 64 bytes should revert
|
|
180
186
|
bytes memory shortInput = hex"deadbeef";
|
|
181
|
-
vm.expectRevert("Input too short, should be at least
|
|
187
|
+
vm.expectRevert("Input too short, should be at least 68 bytes");
|
|
182
188
|
this.exposedNewInputNotPaying(shortInput, self, ETypes.Uint256);
|
|
183
189
|
}
|
|
184
190
|
|
|
@@ -188,10 +194,11 @@ contract TestHandleMetadata is
|
|
|
188
194
|
bytes memory ciphertext = abi.encode(ciphertextData);
|
|
189
195
|
// Create input with wrong handle (just a random bytes32)
|
|
190
196
|
bytes32 wrongHandle = bytes32(uint256(12345));
|
|
191
|
-
|
|
197
|
+
int32 version = 0; // unspecified
|
|
198
|
+
bytes memory badInput = abi.encodePacked(version, abi.encode(wrongHandle, ciphertext));
|
|
192
199
|
|
|
193
200
|
// Compute the expected handle for the error message
|
|
194
|
-
bytes32 expectedHandle = getInputHandle(ciphertext, address(this), self, address(this), ETypes.Uint256);
|
|
201
|
+
bytes32 expectedHandle = getInputHandle(ciphertext, address(this), self, address(this), version, ETypes.Uint256);
|
|
195
202
|
|
|
196
203
|
vm.expectRevert(
|
|
197
204
|
abi.encodeWithSelector(
|
|
@@ -201,7 +208,8 @@ contract TestHandleMetadata is
|
|
|
201
208
|
block.chainid,
|
|
202
209
|
address(this),
|
|
203
210
|
self,
|
|
204
|
-
address(this)
|
|
211
|
+
address(this),
|
|
212
|
+
version
|
|
205
213
|
)
|
|
206
214
|
);
|
|
207
215
|
this.exposedNewInputNotPaying(badInput, self, ETypes.Uint256);
|
|
@@ -4,6 +4,7 @@ pragma solidity ^0.8;
|
|
|
4
4
|
import {StorageSlot} from "@openzeppelin/contracts/utils/StorageSlot.sol";
|
|
5
5
|
|
|
6
6
|
// Re-export FEE constant for convenience - consumers can import both IncoUtils and FEE from this file
|
|
7
|
+
// forge-lint: disable-next-line(unused-import)
|
|
7
8
|
import {FEE} from "../lightning-parts/Fee.sol";
|
|
8
9
|
|
|
9
10
|
contract IncoUtils {
|
|
@@ -12,18 +12,33 @@ import {
|
|
|
12
12
|
import {Version} from "../version/Version.sol";
|
|
13
13
|
import {ALLOWANCE_GRANTED_MAGIC_VALUE} from "../Types.sol";
|
|
14
14
|
|
|
15
|
-
/// @notice
|
|
16
|
-
/// @dev
|
|
15
|
+
/// @notice A Session grants temporary access to a decrypter for all data held by the sharer
|
|
16
|
+
/// @dev ABI encode this struct in the sharerArgData field of the voucher.
|
|
17
|
+
/// The session is valid only if:
|
|
18
|
+
/// 1. The current block timestamp is before expiresAt
|
|
19
|
+
/// 2. The requesting account matches the authorized decrypter
|
|
17
20
|
struct Session {
|
|
21
|
+
/// @notice The address authorized to decrypt the sharer's data
|
|
18
22
|
address decrypter;
|
|
23
|
+
/// @notice Unix timestamp after which the session is no longer valid
|
|
19
24
|
uint256 expiresAt;
|
|
20
25
|
}
|
|
21
26
|
|
|
22
|
-
/// @
|
|
23
|
-
///
|
|
24
|
-
/// @dev
|
|
27
|
+
/// @title SessionVerifier
|
|
28
|
+
/// @notice Inco access sharing verifier for browser dApp sessions
|
|
29
|
+
/// @dev Grants access to all encrypted data held by the sharer to one decrypter for a limited time.
|
|
30
|
+
/// This is the recommended pattern for dApps that need to decrypt user data during a browsing session.
|
|
31
|
+
///
|
|
32
|
+
/// Usage:
|
|
33
|
+
/// 1. User signs a voucher containing a Session struct with their chosen decrypter and expiration
|
|
34
|
+
/// 2. The voucher specifies canUseSession.selector as the callFunction
|
|
35
|
+
/// 3. When the decrypter requests access, this contract verifies the session is still valid
|
|
36
|
+
///
|
|
37
|
+
/// To use this verifier, set the voucher's callFunction to SessionVerifier.canUseSession.selector
|
|
25
38
|
contract SessionVerifier is UUPSUpgradeable, OwnableUpgradeable, Version {
|
|
26
39
|
|
|
40
|
+
/// @notice Initializes the SessionVerifier with version information
|
|
41
|
+
/// @param salt Unique salt used for deterministic deployment via CreateX
|
|
27
42
|
constructor(bytes32 salt)
|
|
28
43
|
Version(
|
|
29
44
|
SESSION_VERIFIER_MAJOR_VERSION,
|
|
@@ -34,7 +49,13 @@ contract SessionVerifier is UUPSUpgradeable, OwnableUpgradeable, Version {
|
|
|
34
49
|
)
|
|
35
50
|
{}
|
|
36
51
|
|
|
37
|
-
|
|
52
|
+
/// @notice Verifies if an account can use a session to access encrypted data
|
|
53
|
+
/// @dev This function is called by the ACL system when validating access permissions.
|
|
54
|
+
/// The session grants blanket access to all handles owned by the sharer - the handle
|
|
55
|
+
/// parameter is intentionally ignored.
|
|
56
|
+
/// @param account The address requesting access (must match session.decrypter)
|
|
57
|
+
/// @param sharerArgData ABI-encoded Session struct containing decrypter address and expiration
|
|
58
|
+
/// @return ALLOWANCE_GRANTED_MAGIC_VALUE if session is valid, bytes32(0) otherwise
|
|
38
59
|
function canUseSession(
|
|
39
60
|
bytes32, /* handle */
|
|
40
61
|
address account,
|
|
@@ -54,14 +75,21 @@ contract SessionVerifier is UUPSUpgradeable, OwnableUpgradeable, Version {
|
|
|
54
75
|
return bytes32(0);
|
|
55
76
|
}
|
|
56
77
|
|
|
78
|
+
/// @notice Authorizes contract upgrades (restricted to owner only)
|
|
79
|
+
/// @dev Required by UUPSUpgradeable. Only the contract owner can upgrade.
|
|
57
80
|
function _authorizeUpgrade(address) internal view override {
|
|
58
81
|
require(msg.sender == owner());
|
|
59
82
|
}
|
|
60
83
|
|
|
84
|
+
/// @notice Initializes the contract with an owner address
|
|
85
|
+
/// @dev Must be called immediately after deployment via proxy. Can only be called once.
|
|
86
|
+
/// @param owner The address that will own this contract and can authorize upgrades
|
|
61
87
|
function initialize(address owner) public initializer {
|
|
62
88
|
__Ownable_init(owner);
|
|
63
89
|
}
|
|
64
90
|
|
|
65
|
-
|
|
91
|
+
/// @notice Required for CreateX deterministic deployment
|
|
92
|
+
/// @dev Empty fallback allows the contract to be deployed via CreateX's create2 mechanism
|
|
93
|
+
fallback() external {}
|
|
66
94
|
|
|
67
95
|
}
|
|
@@ -19,8 +19,16 @@ contract FakeIncoInfraBase is TestUtils, KVStore, HandleGeneration {
|
|
|
19
19
|
{
|
|
20
20
|
// We need a single word here to get correct encoding
|
|
21
21
|
bytes memory ciphertext = abi.encode(word);
|
|
22
|
-
bytes32 handle = getInputHandle(
|
|
23
|
-
|
|
22
|
+
bytes32 handle = getInputHandle(
|
|
23
|
+
ciphertext,
|
|
24
|
+
address(inco),
|
|
25
|
+
user,
|
|
26
|
+
contractAddress,
|
|
27
|
+
0,
|
|
28
|
+
/* unspecified */
|
|
29
|
+
inputType
|
|
30
|
+
);
|
|
31
|
+
input = abi.encodePacked(int32(0), abi.encode(handle, ciphertext));
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
function fakePrepareEuint256Ciphertext(uint256 value, address userAddress, address contractAddress)
|
|
@@ -63,7 +63,7 @@ contract MockOpHandler is FakeIncoInfraBase, FakeComputeServer {
|
|
|
63
63
|
} else if (op == EOps.NewInput) {
|
|
64
64
|
bytes32 result = log.topics[1];
|
|
65
65
|
// contractAddress and user topics are ignored
|
|
66
|
-
(bytes memory ciphertext,) = abi.decode(log.data, (bytes, uint256));
|
|
66
|
+
(, bytes memory ciphertext,) = abi.decode(log.data, (int32, bytes, uint256));
|
|
67
67
|
handleEInput(result, ciphertext);
|
|
68
68
|
}
|
|
69
69
|
}
|