@inco/lightning 0.6.8 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +29 -2
  3. package/manifest.yaml +35 -42
  4. package/package.json +5 -2
  5. package/src/CreateXHelper.sol +3 -1
  6. package/src/DeployUtils.sol +36 -71
  7. package/src/Errors.sol +1 -1
  8. package/src/IIncoLightning.sol +2 -0
  9. package/src/IncoLightning.sol +5 -17
  10. package/src/IncoVerifier.sol +12 -18
  11. package/src/Lib.alphanet.sol +1 -1
  12. package/src/Lib.sol +1 -1
  13. package/src/Lib.template.sol +35 -153
  14. package/src/Types.sol +231 -97
  15. package/src/interfaces/IIncoLightning.sol +2 -0
  16. package/src/interfaces/IIncoVerifier.sol +6 -12
  17. package/src/interfaces/automata-interfaces/BELE.sol +2 -0
  18. package/src/interfaces/automata-interfaces/IAutomataEnclaveIdentityDao.sol +9 -11
  19. package/src/interfaces/automata-interfaces/IFmspcTcbDao.sol +3 -3
  20. package/src/interfaces/automata-interfaces/IPCCSRouter.sol +13 -47
  21. package/src/interfaces/automata-interfaces/IPCCSRouterExtended.sol +2 -0
  22. package/src/interfaces/automata-interfaces/IPcsDao.sol +6 -11
  23. package/src/interfaces/automata-interfaces/IQuoteVerifier.sol +4 -7
  24. package/src/interfaces/automata-interfaces/Types.sol +7 -6
  25. package/src/libs/incoLightning_alphanet_v2_976644394.sol +478 -0
  26. package/src/libs/incoLightning_devnet_v1_887305889.sol +5 -3
  27. package/src/libs/incoLightning_testnet_v1_938327937.sol +5 -3
  28. package/src/lightning-parts/AccessControl/AdvancedAccessControl.sol +39 -72
  29. package/src/lightning-parts/AccessControl/BaseAccessControlList.sol +31 -62
  30. package/src/lightning-parts/AccessControl/interfaces/IAdvancedAccessControl.sol +8 -15
  31. package/src/lightning-parts/AccessControl/interfaces/IBaseAccessControlList.sol +5 -12
  32. package/src/lightning-parts/AccessControl/test/TestAdvancedAccessControl.t.sol +44 -84
  33. package/src/lightning-parts/AccessControl/test/TestBaseAccessControl.t.sol +2 -0
  34. package/src/lightning-parts/DecryptionAttester.sol +14 -28
  35. package/src/lightning-parts/EncryptedInput.sol +23 -52
  36. package/src/lightning-parts/EncryptedOperations.sol +96 -438
  37. package/src/lightning-parts/Fee.sol +3 -1
  38. package/src/lightning-parts/TEELifecycle.sol +94 -223
  39. package/src/lightning-parts/TEELifecycle.types.sol +4 -3
  40. package/src/lightning-parts/TrivialEncryption.sol +6 -20
  41. package/src/lightning-parts/interfaces/IDecryptionAttester.sol +7 -2
  42. package/src/lightning-parts/interfaces/IEncryptedInput.sol +5 -12
  43. package/src/lightning-parts/interfaces/IEncryptedOperations.sol +17 -61
  44. package/src/lightning-parts/interfaces/ITEELifecycle.sol +7 -11
  45. package/src/lightning-parts/interfaces/ITrivialEncryption.sol +2 -0
  46. package/src/lightning-parts/primitives/EventCounter.sol +7 -8
  47. package/src/lightning-parts/primitives/HandleGeneration.sol +20 -32
  48. package/src/lightning-parts/primitives/HandleMetadata.sol +7 -17
  49. package/src/lightning-parts/primitives/LightningAddressGetter.sol +3 -0
  50. package/src/lightning-parts/primitives/SignatureVerifier.sol +91 -27
  51. package/src/lightning-parts/primitives/VerifierAddressGetter.sol +3 -0
  52. package/src/lightning-parts/primitives/interfaces/IEventCounter.sol +2 -0
  53. package/src/lightning-parts/primitives/interfaces/IHandleGeneration.sol +10 -2
  54. package/src/lightning-parts/primitives/interfaces/ISignatureVerifier.sol +4 -2
  55. package/src/lightning-parts/primitives/interfaces/IVerifierAddressGetter.sol +2 -0
  56. package/src/lightning-parts/primitives/test/SignatureVerifier.t.sol +838 -0
  57. package/src/lightning-parts/test/Fee.t.sol +6 -6
  58. package/src/lightning-parts/test/HandleMetadata.t.sol +21 -76
  59. package/src/lightning-parts/test/InputsFee.t.sol +7 -28
  60. package/src/lightning-parts/test/TestDecryptionAttestationInSynchronousFlow.t.sol +16 -48
  61. package/src/pasted-dependencies/CreateX.sol +154 -455
  62. package/src/pasted-dependencies/ICreateX.sol +55 -102
  63. package/src/periphery/SessionVerifier.sol +10 -8
  64. package/src/shared/IOwnable.sol +3 -0
  65. package/src/shared/IUUPSUpgradable.sol +5 -1
  66. package/src/shared/JsonUtils.sol +3 -5
  67. package/src/shared/TestUtils.sol +15 -13
  68. package/src/test/AddTwo.sol +9 -7
  69. package/src/test/FakeIncoInfra/FakeComputeServer.sol +11 -53
  70. package/src/test/FakeIncoInfra/FakeDecryptionAttester.sol +35 -119
  71. package/src/test/FakeIncoInfra/FakeIncoInfraBase.sol +31 -48
  72. package/src/test/FakeIncoInfra/FakeQuoteVerifier.sol +4 -7
  73. package/src/test/FakeIncoInfra/KVStore.sol +2 -0
  74. package/src/test/FakeIncoInfra/MockOpHandler.sol +9 -31
  75. package/src/test/FakeIncoInfra/MockRemoteAttestation.sol +50 -21
  76. package/src/test/IncoTest.sol +22 -9
  77. package/src/test/OpsTest.sol +438 -0
  78. package/src/test/TEELifecycle/TEELifecycleMockTest.t.sol +57 -104
  79. package/src/test/TestAddTwo.t.sol +4 -3
  80. package/src/test/TestDeploy.t.sol +5 -6
  81. package/src/test/TestExtractDataOfEventTooLarge.t.sol +7 -9
  82. package/src/test/TestFakeInfra.t.sol +15 -38
  83. package/src/test/TestUpgrade.t.sol +40 -135
  84. package/src/test/TestVersion.t.sol +6 -5
  85. package/src/version/IncoLightningConfig.sol +2 -2
  86. package/src/version/Version.sol +46 -48
  87. package/src/version/interfaces/IVersion.sol +6 -0
@@ -4,75 +4,31 @@ pragma solidity ^0.8;
4
4
  import {euint256, ebool, ETypes} from "../../Types.sol";
5
5
 
6
6
  interface IEncryptedOperations {
7
- function eAdd(
8
- euint256 lhs,
9
- euint256 rhs
10
- ) external returns (euint256 result);
11
- function eSub(
12
- euint256 lhs,
13
- euint256 rhs
14
- ) external returns (euint256 result);
15
- function eMul(
16
- euint256 lhs,
17
- euint256 rhs
18
- ) external returns (euint256 result);
19
- function eDiv(
20
- euint256 lhs,
21
- euint256 rhs
22
- ) external returns (euint256 result);
23
- function eRem(
24
- euint256 lhs,
25
- euint256 rhs
26
- ) external returns (euint256 result);
27
- function eBitAnd(
28
- bytes32 lhs,
29
- bytes32 rhs
30
- ) external returns (bytes32 result);
7
+
8
+ function eAdd(euint256 lhs, euint256 rhs) external returns (euint256 result);
9
+ function eSub(euint256 lhs, euint256 rhs) external returns (euint256 result);
10
+ function eMul(euint256 lhs, euint256 rhs) external returns (euint256 result);
11
+ function eDiv(euint256 lhs, euint256 rhs) external returns (euint256 result);
12
+ function eRem(euint256 lhs, euint256 rhs) external returns (euint256 result);
13
+ function eBitAnd(bytes32 lhs, bytes32 rhs) external returns (bytes32 result);
31
14
  function eBitOr(bytes32 lhs, bytes32 rhs) external returns (bytes32 result);
32
- function eBitXor(
33
- bytes32 lhs,
34
- bytes32 rhs
35
- ) external returns (bytes32 result);
36
- function eShl(
37
- euint256 lhs,
38
- euint256 rhs
39
- ) external returns (euint256 result);
40
- function eShr(
41
- euint256 lhs,
42
- euint256 rhs
43
- ) external returns (euint256 result);
44
- function eRotl(
45
- euint256 lhs,
46
- euint256 rhs
47
- ) external returns (euint256 result);
48
- function eRotr(
49
- euint256 lhs,
50
- euint256 rhs
51
- ) external returns (euint256 result);
15
+ function eBitXor(bytes32 lhs, bytes32 rhs) external returns (bytes32 result);
16
+ function eShl(euint256 lhs, euint256 rhs) external returns (euint256 result);
17
+ function eShr(euint256 lhs, euint256 rhs) external returns (euint256 result);
18
+ function eRotl(euint256 lhs, euint256 rhs) external returns (euint256 result);
19
+ function eRotr(euint256 lhs, euint256 rhs) external returns (euint256 result);
52
20
  function eEq(bytes32 lhs, bytes32 rhs) external returns (ebool result);
53
21
  function eNe(bytes32 lhs, bytes32 rhs) external returns (ebool result);
54
22
  function eGe(euint256 lhs, euint256 rhs) external returns (ebool result);
55
23
  function eGt(euint256 lhs, euint256 rhs) external returns (ebool result);
56
24
  function eLe(euint256 lhs, euint256 rhs) external returns (ebool result);
57
25
  function eLt(euint256 lhs, euint256 rhs) external returns (ebool result);
58
- function eMin(
59
- euint256 lhs,
60
- euint256 rhs
61
- ) external returns (euint256 result);
62
- function eMax(
63
- euint256 lhs,
64
- euint256 rhs
65
- ) external returns (euint256 result);
26
+ function eMin(euint256 lhs, euint256 rhs) external returns (euint256 result);
27
+ function eMax(euint256 lhs, euint256 rhs) external returns (euint256 result);
66
28
  function eNot(ebool operand) external returns (ebool result);
67
29
  function eCast(bytes32 ct, ETypes toType) external returns (bytes32 result);
68
30
  function eRand(ETypes randType) external payable returns (bytes32 result);
69
- function eRandBounded(
70
- bytes32 upperBound,
71
- ETypes randType
72
- ) external payable returns (bytes32 result);
73
- function eIfThenElse(
74
- ebool condition,
75
- bytes32 ifTrue,
76
- bytes32 ifFalse
77
- ) external returns (bytes32 result);
31
+ function eRandBounded(bytes32 upperBound, ETypes randType) external payable returns (bytes32 result);
32
+ function eIfThenElse(ebool condition, bytes32 ifTrue, bytes32 ifFalse) external returns (bytes32 result);
33
+
78
34
  }
@@ -3,9 +3,10 @@ pragma solidity ^0.8.19;
3
3
 
4
4
  import {BootstrapResult, UpgradeResult, AddNodeResult} from "../TEELifecycle.types.sol";
5
5
  import {IQuoteVerifier} from "../../interfaces/automata-interfaces/IQuoteVerifier.sol";
6
- import {TD10ReportBody} from "../../interfaces/automata-interfaces/Types.sol";
6
+ import {Td10ReportBody} from "../../interfaces/automata-interfaces/Types.sol";
7
7
 
8
8
  interface ITEELifecycle {
9
+
9
10
  function verifyBootstrapResult(
10
11
  BootstrapResult calldata bootstrapResult,
11
12
  bytes calldata quote,
@@ -23,15 +24,10 @@ interface ITEELifecycle {
23
24
  bytes calldata quote,
24
25
  bytes calldata signature
25
26
  ) external;
26
- function approveNewTEEVersion(bytes32 newMrAggregated) external;
27
- function parseTD10ReportBody(
28
- bytes calldata rawQuote
29
- ) external pure returns (TD10ReportBody memory report);
30
- function parseReport(
31
- TD10ReportBody memory tdReport
32
- ) external pure returns (address, bytes32);
33
- function bootstrapResultDigest(
34
- BootstrapResult memory bootstrapResult
35
- ) external view returns (bytes32);
27
+ function approveNewTeeVersion(bytes32 newMrAggregated) external;
28
+ function parseTd10ReportBody(bytes calldata rawQuote) external pure returns (Td10ReportBody memory report);
29
+ function parseReport(Td10ReportBody memory tdReport) external pure returns (address, bytes32);
30
+ function bootstrapResultDigest(BootstrapResult memory bootstrapResult) external view returns (bytes32);
36
31
  function quoteVerifier() external view returns (IQuoteVerifier);
32
+
37
33
  }
@@ -4,7 +4,9 @@ pragma solidity ^0.8;
4
4
  import {euint256, ebool, eaddress} from "../../Types.sol";
5
5
 
6
6
  interface ITrivialEncryption {
7
+
7
8
  function asEuint256(uint256 value) external returns (euint256 newEuint256);
8
9
  function asEbool(bool value) external returns (ebool newEbool);
9
10
  function asEaddress(address value) external returns (eaddress newEaddress);
11
+
10
12
  }
@@ -4,27 +4,25 @@ pragma solidity ^0.8;
4
4
  import {IEventCounter} from "./interfaces/IEventCounter.sol";
5
5
 
6
6
  contract EventCounterStorage {
7
+
7
8
  struct Storage {
8
9
  // TODO: change type to bytes32 when we rename away from "counter".
9
10
  uint256 eventCounter;
10
11
  }
11
12
 
12
- bytes32 private constant eventCounterStorageLocation =
13
- keccak256("lightning.storage.EventCounter");
13
+ bytes32 private constant EVENT_COUNTER_STORAGE_LOCATION = keccak256("lightning.storage.EventCounter");
14
14
 
15
- function getEventCounterStorage()
16
- internal
17
- pure
18
- returns (Storage storage $)
19
- {
20
- bytes32 loc = eventCounterStorageLocation;
15
+ function getEventCounterStorage() internal pure returns (Storage storage $) {
16
+ bytes32 loc = EVENT_COUNTER_STORAGE_LOCATION;
21
17
  assembly {
22
18
  $.slot := loc
23
19
  }
24
20
  }
21
+
25
22
  }
26
23
 
27
24
  contract EventCounter is IEventCounter, EventCounterStorage {
25
+
28
26
  function getNewEventId() internal returns (uint256 newEventId) {
29
27
  newEventId = getEventCounterStorage().eventCounter++;
30
28
  }
@@ -43,4 +41,5 @@ contract EventCounter is IEventCounter, EventCounterStorage {
43
41
  function getEventCounter() public view returns (uint256) {
44
42
  return getNextEventId();
45
43
  }
44
+
46
45
  }
@@ -1,20 +1,17 @@
1
1
  // SPDX-License-Identifier: No License
2
2
  pragma solidity ^0.8;
3
3
 
4
- import {
5
- ETypes,
6
- EOps,
7
- EVM_HOST_CHAIN_PREFIX,
8
- HANDLE_INDEX
9
- } from "../../Types.sol";
4
+ import {ETypes, EOps, EVM_HOST_CHAIN_PREFIX, HANDLE_INDEX} from "../../Types.sol";
10
5
  import {HandleMetadata} from "./HandleMetadata.sol";
11
6
  import {IHandleGeneration} from "./interfaces/IHandleGeneration.sol";
12
7
 
13
8
  contract HandleGeneration is IHandleGeneration, HandleMetadata {
14
- function getTrivialEncryptHandle(
15
- bytes32 plaintextBytes,
16
- ETypes handleType
17
- ) public view returns (bytes32 generatedHandle) {
9
+
10
+ function getTrivialEncryptHandle(bytes32 plaintextBytes, ETypes handleType)
11
+ public
12
+ pure
13
+ returns (bytes32 generatedHandle)
14
+ {
18
15
  generatedHandle = keccak256(
19
16
  abi.encodePacked(
20
17
  EOps.TrivialEncrypt, // !! Note[Silas]: I reordered this to be first element for greater regularity 26/08/2025 (remove this note after 1 month) !!
@@ -24,20 +21,12 @@ contract HandleGeneration is IHandleGeneration, HandleMetadata {
24
21
  generatedHandle = embedTypeVersion(generatedHandle, handleType);
25
22
  }
26
23
 
27
- function getInputHandle(
28
- bytes memory ciphertext,
29
- address user,
30
- address contractAddress,
31
- ETypes inputType
32
- ) internal view returns (bytes32 generatedHandle) {
33
- return
34
- getInputHandle(
35
- ciphertext,
36
- address(this),
37
- user,
38
- contractAddress,
39
- inputType
40
- );
24
+ function getInputHandle(bytes memory ciphertext, address user, address contractAddress, ETypes inputType)
25
+ internal
26
+ view
27
+ returns (bytes32 generatedHandle)
28
+ {
29
+ return getInputHandle(ciphertext, address(this), user, contractAddress, inputType);
41
30
  }
42
31
 
43
32
  function getInputHandle(
@@ -49,9 +38,7 @@ contract HandleGeneration is IHandleGeneration, HandleMetadata {
49
38
  ) internal view returns (bytes32 generatedHandle) {
50
39
  // Here we ensure that our hashing scheme is binary-compatible between IncoLightning and IncoFhevm, this helps
51
40
  // keep client-side code consistent in its ciphertext, context => handle mappings
52
- bytes32 ctIndexHash = keccak256(
53
- abi.encodePacked(keccak256(ciphertext), HANDLE_INDEX)
54
- );
41
+ bytes32 ctIndexHash = keccak256(abi.encodePacked(keccak256(ciphertext), HANDLE_INDEX));
55
42
  bytes32 prehandle = embedIndexTypeVersion(ctIndexHash, inputType);
56
43
  // We must also propagate the handle metadata to the final handle
57
44
  generatedHandle = embedIndexTypeVersion(
@@ -69,11 +56,12 @@ contract HandleGeneration is IHandleGeneration, HandleMetadata {
69
56
  );
70
57
  }
71
58
 
72
- function getOpResultHandle(
73
- EOps op,
74
- ETypes returnType,
75
- bytes memory packedInputs
76
- ) public pure returns (bytes32 generatedHandle) {
59
+ function getOpResultHandle(EOps op, ETypes returnType, bytes memory packedInputs)
60
+ public
61
+ pure
62
+ returns (bytes32 generatedHandle)
63
+ {
77
64
  generatedHandle = embedTypeVersion(keccak256(abi.encodePacked(op, packedInputs)), returnType);
78
65
  }
66
+
79
67
  }
@@ -1,19 +1,13 @@
1
1
  // SPDX-License-Identifier: No License
2
2
  pragma solidity ^0.8;
3
3
 
4
- import { HANDLE_VERSION, HANDLE_INDEX, ETypes } from "../../Types.sol";
4
+ import {HANDLE_VERSION, HANDLE_INDEX, ETypes} from "../../Types.sol";
5
5
 
6
6
  contract HandleMetadata {
7
- function embedIndexTypeVersion(
8
- bytes32 prehandle,
9
- ETypes inputType
10
- ) internal pure returns (bytes32 result) {
7
+
8
+ function embedIndexTypeVersion(bytes32 prehandle, ETypes inputType) internal pure returns (bytes32 result) {
11
9
  // Create a mask to clear the last three bytes
12
- bytes32 mask = bytes32(
13
- uint256(
14
- 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFF
15
- )
16
- );
10
+ bytes32 mask = bytes32(uint256(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFF));
17
11
  // Clear the last three bytes of the original value
18
12
  bytes32 clearedOriginal = prehandle & mask;
19
13
  // Combine the cleared original value with the new last three bytes
@@ -21,13 +15,8 @@ contract HandleMetadata {
21
15
  result = embedTypeVersion(result, inputType);
22
16
  }
23
17
 
24
- function embedTypeVersion(
25
- bytes32 prehandle,
26
- ETypes handleType
27
- ) internal pure returns (bytes32 result) {
28
- result =
29
- prehandle &
30
- 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000;
18
+ function embedTypeVersion(bytes32 prehandle, ETypes handleType) internal pure returns (bytes32 result) {
19
+ result = prehandle & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000;
31
20
  result = bytes32(uint256(result) | (uint256(handleType) << 8)); // append type
32
21
  result = bytes32(uint256(result) | HANDLE_VERSION);
33
22
  }
@@ -35,4 +24,5 @@ contract HandleMetadata {
35
24
  function typeOf(bytes32 handle) internal pure returns (ETypes) {
36
25
  return ETypes(uint8(uint256(handle) >> 8));
37
26
  }
27
+
38
28
  }
@@ -2,9 +2,12 @@
2
2
  pragma solidity ^0.8;
3
3
 
4
4
  abstract contract LightningAddressGetter {
5
+
6
+ // forge-lint: disable-next-line(screaming-snake-case-immutable)
5
7
  address internal immutable incoLightningAddress;
6
8
 
7
9
  constructor(address _incoLightningAddress) {
8
10
  incoLightningAddress = _incoLightningAddress;
9
11
  }
12
+
10
13
  }
@@ -4,64 +4,128 @@ pragma solidity ^0.8;
4
4
  import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
5
5
  import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
6
6
  import {ISignatureVerifier} from "./interfaces/ISignatureVerifier.sol";
7
- import {TEELifecycle} from "../TEELifecycle.sol";
8
7
 
9
8
  contract SignatureVerifierStorage {
9
+
10
10
  struct StorageForSigVerifier {
11
+ address[] signers;
11
12
  mapping(address => bool) isSigner;
13
+ uint256 threshold;
12
14
  }
13
15
 
14
16
  // State changelog:
15
17
  // 0.2.0: Shifting state location to support multiple signers
16
- bytes32 private constant SignatureVerifierStorageLocation =
17
- keccak256("inco.storage.SignatureVerifier.v0.2.0");
18
-
19
- function getSigVerifierStorage()
20
- internal
21
- pure
22
- returns (StorageForSigVerifier storage $)
23
- {
24
- bytes32 loc = SignatureVerifierStorageLocation;
18
+ bytes32 private constant SIGNATURE_VERIFIER_STORAGE_LOCATION = keccak256("inco.storage.SignatureVerifier.v0.2.0");
19
+
20
+ function getSigVerifierStorage() internal pure returns (StorageForSigVerifier storage $) {
21
+ bytes32 loc = SIGNATURE_VERIFIER_STORAGE_LOCATION;
25
22
  assembly {
26
23
  $.slot := loc
27
24
  }
28
25
  }
26
+
29
27
  }
30
28
 
31
29
  abstract contract SignatureVerifier is ISignatureVerifier, OwnableUpgradeable, SignatureVerifierStorage {
30
+
31
+ // we use ECDSA as the signers are meant to be EOAs controlled by TEEs, and no smart contract wallet
32
32
  using ECDSA for bytes32;
33
33
 
34
34
  error SignerNotFound(address signerAddress);
35
+ error SignerAlreadyAdded(address signerAddress);
36
+ error InvalidThreshold(uint256 threshold, uint256 nbOfSigners);
37
+ error SignersNotInAscendingOrder(address currentSigner, address lastSigner);
35
38
 
36
39
  event AddedSignatureVerifier(address signerAddress);
37
40
  event RemovedSignatureVerifier(address signerAddress);
41
+ event ThresholdChanged(uint256 oldThreshold, uint256 newThreshold);
38
42
 
39
- // @todo: This function should be removed once we have a way to read the signers from the TEELifecycle contract
40
- function addSigner(address signerAddress) external onlyOwner {
41
- getSigVerifierStorage().isSigner[signerAddress] = true;
43
+ /// @dev internal sensible function, should be used only as part of an onlyOwner function / access controlled
44
+ function addSigner(address signerAddress) internal {
45
+ StorageForSigVerifier storage $ = getSigVerifierStorage();
46
+ require(!isSigner(signerAddress), SignerAlreadyAdded(signerAddress));
47
+ $.signers.push(signerAddress);
48
+ $.isSigner[signerAddress] = true;
42
49
  emit AddedSignatureVerifier(signerAddress);
43
50
  }
44
51
 
45
- // @todo: This function should be removed once we have a way to read the signers from the TEELifecycle contract
46
52
  function removeSigner(address signerAddress) external onlyOwner {
47
- require(
48
- getSigVerifierStorage().isSigner[signerAddress],
49
- SignerNotFound(signerAddress)
50
- );
51
- getSigVerifierStorage().isSigner[signerAddress] = false;
52
- emit AddedSignatureVerifier(signerAddress);
53
+ StorageForSigVerifier storage $ = getSigVerifierStorage();
54
+ require(isSigner(signerAddress), SignerNotFound(signerAddress));
55
+ require($.signers.length - 1 >= $.threshold, InvalidThreshold($.threshold, $.signers.length - 1));
56
+
57
+ // Find and remove the signer from the array
58
+ for (uint256 i = 0; i < $.signers.length; i++) {
59
+ if ($.signers[i] == signerAddress) {
60
+ // Move the last element to this position and pop
61
+ $.signers[i] = $.signers[$.signers.length - 1];
62
+ $.signers.pop();
63
+ break;
64
+ }
65
+ }
66
+
67
+ $.isSigner[signerAddress] = false;
68
+ emit RemovedSignatureVerifier(signerAddress);
69
+ }
70
+
71
+ function setThreshold(uint256 newThreshold) external onlyOwner {
72
+ StorageForSigVerifier storage $ = getSigVerifierStorage();
73
+ require(newThreshold <= $.signers.length, InvalidThreshold(newThreshold, $.signers.length));
74
+ require(newThreshold > 0, InvalidThreshold(newThreshold, $.signers.length));
75
+
76
+ uint256 oldThreshold = $.threshold;
77
+ $.threshold = newThreshold;
78
+ emit ThresholdChanged(oldThreshold, newThreshold);
79
+ }
80
+
81
+ function getThreshold() public view returns (uint256) {
82
+ return getSigVerifierStorage().threshold;
53
83
  }
54
84
 
55
- // @todo: This function should read from the TEELifecycle contract instead of the storage
56
85
  function isSigner(address signerAddress) public view returns (bool) {
57
86
  return getSigVerifierStorage().isSigner[signerAddress];
58
87
  }
59
88
 
60
- function isValidSignature(
61
- bytes32 hash,
62
- bytes memory signature
63
- ) public view returns (bool) {
64
- address signerAddress = hash.recover(signature);
65
- return getSigVerifierStorage().isSigner[signerAddress];
89
+ /// @dev each signer id is NOT fixed, it can change over time, be removed, readded, etc.
90
+ function getSignerAtIndex(uint256 index) public view returns (address) {
91
+ return getSigVerifierStorage().signers[index];
66
92
  }
93
+
94
+ function getSignersCount() public view returns (uint256) {
95
+ return getSigVerifierStorage().signers.length;
96
+ }
97
+
98
+ /// @dev signature signers MUST be in ascending order, reverts with SignersNotInAscendingOrder if not
99
+ /// @dev signatures beyond the threshold are ignored
100
+ function isValidSignature(bytes32 digest, bytes[] memory signatures) public view returns (bool) {
101
+ StorageForSigVerifier storage $ = getSigVerifierStorage();
102
+ uint256 threshold = $.threshold;
103
+ uint256 signaturesLength = signatures.length;
104
+
105
+ // if threshold is 0, we can't accept any signatures yet
106
+ if (threshold == 0 || signaturesLength < threshold) {
107
+ return false;
108
+ }
109
+
110
+ address lastSigner = address(0);
111
+ uint256 correctSignaturesCount = 0;
112
+ uint256 i = 0;
113
+
114
+ while (correctSignaturesCount < threshold && i < signaturesLength) {
115
+ address currentSigner = digest.recover(signatures[i]);
116
+
117
+ // Ensure signers are in ascending order to prevent duplicates
118
+ // Revert is used instead of return false to signal the user/developer an error (call malformed) is on his side
119
+ require(currentSigner > lastSigner, SignersNotInAscendingOrder(currentSigner, lastSigner));
120
+ lastSigner = currentSigner;
121
+
122
+ if (isSigner(currentSigner)) {
123
+ correctSignaturesCount++;
124
+ }
125
+ i++;
126
+ }
127
+
128
+ return correctSignaturesCount >= threshold;
129
+ }
130
+
67
131
  }
@@ -5,9 +5,12 @@ import {IIncoVerifier} from "../../interfaces/IIncoVerifier.sol";
5
5
  import {IVerifierAddressGetter} from "./interfaces/IVerifierAddressGetter.sol";
6
6
 
7
7
  abstract contract VerifierAddressGetter is IVerifierAddressGetter {
8
+
9
+ // forge-lint: disable-next-line(screaming-snake-case-immutable)
8
10
  IIncoVerifier public immutable incoVerifier;
9
11
 
10
12
  constructor(address _incoVerifier) {
11
13
  incoVerifier = IIncoVerifier(_incoVerifier);
12
14
  }
15
+
13
16
  }
@@ -2,7 +2,9 @@
2
2
  pragma solidity ^0.8;
3
3
 
4
4
  interface IEventCounter {
5
+
5
6
  function getNextEventId() external view returns (uint256);
6
7
 
7
8
  function getEventCounter() external view returns (uint256);
9
+
8
10
  }
@@ -4,7 +4,15 @@ pragma solidity ^0.8;
4
4
  import {ETypes, EOps} from "../../../Types.sol";
5
5
 
6
6
  interface IHandleGeneration {
7
- function getTrivialEncryptHandle(bytes32 plaintextBytes, ETypes handleType) external view returns (bytes32 generatedHandle);
8
7
 
9
- function getOpResultHandle(EOps op, ETypes returnType, bytes memory packedInputs) external pure returns (bytes32 generatedHandle);
8
+ function getTrivialEncryptHandle(bytes32 plaintextBytes, ETypes handleType)
9
+ external
10
+ view
11
+ returns (bytes32 generatedHandle);
12
+
13
+ function getOpResultHandle(EOps op, ETypes returnType, bytes memory packedInputs)
14
+ external
15
+ pure
16
+ returns (bytes32 generatedHandle);
17
+
10
18
  }
@@ -2,8 +2,10 @@
2
2
  pragma solidity ^0.8;
3
3
 
4
4
  interface ISignatureVerifier {
5
- function addSigner(address signerAddress) external;
5
+
6
6
  function removeSigner(address signerAddress) external;
7
7
  function isSigner(address signerAddress) external view returns (bool);
8
- function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bool);
8
+ function isValidSignature(bytes32 hash, bytes[] memory signatures) external view returns (bool);
9
+ function setThreshold(uint256 newThreshold) external;
10
+
9
11
  }
@@ -4,5 +4,7 @@ pragma solidity ^0.8;
4
4
  import {IIncoVerifier} from "../../../interfaces/IIncoVerifier.sol";
5
5
 
6
6
  interface IVerifierAddressGetter {
7
+
7
8
  function incoVerifier() external view returns (IIncoVerifier);
9
+
8
10
  }