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

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
@@ -6,10 +6,11 @@
6
6
  pragma solidity ^0.8;
7
7
 
8
8
  import { IncoLightning } from "../IncoLightning.sol";
9
- import { ebool, euint256, eaddress, ETypes } from "../Types.sol";
10
- import { DecryptionAttestation } from "../lightning-parts/DecryptionAttester.types.sol";
9
+ import { ebool, euint256, eaddress, ETypes, elist, IndexOutOfRange, InvalidRange, SliceOutOfRange, UnsupportedListType, HandleMismatch, InvalidTEEAttestation, UnexpectedDecryptedValue } from "../Types.sol";
10
+ import { asBool } from "../shared/TypeUtils.sol";
11
+ import { DecryptionAttestation, ElementAttestationWithProof } from "../lightning-parts/DecryptionAttester.types.sol";
11
12
 
12
- IncoLightning constant inco = IncoLightning(0x168FDc3Ae19A5d5b03614578C58974FF30FCBe92);
13
+ IncoLightning constant inco = IncoLightning(payable(0x168FDc3Ae19A5d5b03614578C58974FF30FCBe92));
13
14
  address constant deployedBy = 0x8202D2D747784Cb7D48868E44C42C4bf162a70BC;
14
15
 
15
16
  /// @notice Returns the ETypes enum value encoded in a handle
@@ -687,13 +688,14 @@ library e {
687
688
  /// @dev costs the inco fee
688
689
  /// @return The encrypted random value
689
690
  function rand() internal returns (euint256) {
690
- bytes32 result = _callWithFeeRetry(abi.encodeWithSelector(inco.eRand.selector, ETypes.Uint256));
691
+ bytes32 boundHandle = euint256.unwrap(asEuint256(0));
692
+ bytes32 result = _callWithFeeRetry(abi.encodeWithSelector(inco.eRandBounded.selector, boundHandle, ETypes.Uint256));
691
693
  return euint256.wrap(result);
692
694
  }
693
695
 
694
696
  /// @notice Generates a random encrypted uint256 less than a plaintext upper bound (costs the inco fee)
695
697
  /// @dev costs the inco fee
696
- /// @param upperBound The plaintext upper bound
698
+ /// @param upperBound The plaintext upper bound (exclusive). If the upper bound is 0, the whole 256bit range is sampled, equivalent to providing type(uint256).max as upper bound.
697
699
  /// @return The encrypted random value
698
700
  function randBounded(uint256 upperBound) internal returns (euint256) {
699
701
  bytes32 boundHandle = euint256.unwrap(asEuint256(upperBound));
@@ -703,7 +705,7 @@ library e {
703
705
 
704
706
  /// @notice Generates a random encrypted uint256 less than an encrypted upper bound (costs the inco fee)
705
707
  /// @dev costs the inco fee
706
- /// @param upperBound The encrypted upper bound
708
+ /// @param upperBound The encrypted upper bound (exclusive). If the upper bound is e(0), the whole 256bit range is sampled, equivalent to providing e(type(uint256).max) as upper bound.
707
709
  /// @return The encrypted random value
708
710
  function randBounded(euint256 upperBound) internal returns (euint256) {
709
711
  bytes32 boundHandle = euint256.unwrap(s(upperBound));
@@ -732,13 +734,6 @@ library e {
732
734
  return inco.asEaddress(a);
733
735
  }
734
736
 
735
- /// @notice Casts an encrypted uint256 to an encrypted bool
736
- /// @param a The encrypted uint256 value
737
- /// @return The encrypted bool value
738
- function asEbool(euint256 a) internal returns (ebool) {
739
- return ebool.wrap(inco.eCast(euint256.unwrap(a), ETypes.Bool));
740
- }
741
-
742
737
  /// @notice Casts an encrypted bool to an encrypted uint256
743
738
  /// @param a The encrypted bool value
744
739
  /// @return The encrypted uint256 value
@@ -939,4 +934,290 @@ library e {
939
934
  }
940
935
  return abi.decode(result, (bytes32));
941
936
  }
937
+
938
+ /// @notice Returns the type of the elements contained within the list.
939
+ /// @param handle EList handle to read container type from.
940
+ /// @return ret Type of each element in the list.
941
+ function listTypeOf(elist handle) internal pure returns (ETypes ret) {
942
+ return ETypes(uint8(uint256(elist.unwrap(handle)) >> 16));
943
+ }
944
+
945
+ /// @notice Creates a new empty list. Type must be specified ahead of time and can not be changed.
946
+ /// @param listType Type of each element in the list.
947
+ /// @return ret A new elist handle
948
+ function newEList(ETypes listType) internal returns (elist ret) {
949
+ return inco.newEList(new bytes32[](0), listType);
950
+ }
951
+
952
+ /// @notice Creates a new list from existing array of handles.
953
+ /// @param handles An array of handles to create a new list from
954
+ /// @param listType Type of each element in the list.
955
+ /// @return ret A new elist handle
956
+ function newEList(bytes32[] memory handles, ETypes listType) internal returns (elist ret) {
957
+ return inco.newEList{value: inco.getEListFee(uint16(handles.length), listType)}(handles, listType);
958
+ }
959
+
960
+ /// @notice Takes an array of user encrypted ciphertexts and returns a new elist handle.
961
+ /// @param ciphertexts An array of encrypted user inputs
962
+ /// @param listType Expected type of each element in the list.
963
+ /// @param user Address of the user encrypting the ciphertexts.
964
+ /// @return ret A new elist handle
965
+ /// @dev each ciphertext costs the inco fee
966
+ function newEList(bytes[] memory ciphertexts, ETypes listType, address user) internal returns (elist ret) {
967
+ return inco.newEList{value: inco.getEListFee(uint16(ciphertexts.length), listType)}(ciphertexts, listType, user);
968
+ }
969
+
970
+ /// @notice Appends an ebool element at the end of a list.
971
+ /// @param a An elist handle to append to.
972
+ /// @param b Element value to be appended.
973
+ /// @return ret A new elist handle with length len(a)+1.
974
+ function append(elist a, ebool b) internal returns (elist ret) {
975
+ return inco.listAppend{value: inco.getEListFee(length(a) + 1, listTypeOf(a))}(a, ebool.unwrap(s(b)));
976
+ }
977
+
978
+ /// @notice Appends an euint256 element at the end of a list.
979
+ /// @param a An elist handle to append to.
980
+ /// @param b Element value to be appended.
981
+ /// @return ret A new elist handle with length len(a)+1.
982
+ function append(elist a, euint256 b) internal returns (elist ret) {
983
+ return inco.listAppend{value: inco.getEListFee(length(a) + 1, listTypeOf(a))}(a, euint256.unwrap(s(b)));
984
+ }
985
+
986
+ /// @notice Replaces an element at some hidden index "i" (ebool variant).
987
+ /// @dev If the encrypted index is out of bounds, the operation is silently ignored
988
+ /// and the returned list is identical to the input. This avoids leaking index validity.
989
+ /// @param a EList handle to modify element in.
990
+ /// @param i Hidden index position of an element to modify.
991
+ /// @param b Element value to be changed.
992
+ /// @return ret A new elist handle
993
+ function set(elist a, euint256 i, ebool b) internal returns (elist ret) {
994
+ return inco.listSet{value: inco.getEListFee(length(a), listTypeOf(a))}(a, euint256.unwrap(s(i)), ebool.unwrap(s(b)));
995
+ }
996
+
997
+ /// @notice Replaces an element at some hidden index "i" (euint256 variant).
998
+ /// @dev If the encrypted index is out of bounds, the operation is silently ignored
999
+ /// and the returned list is identical to the input. This avoids leaking index validity.
1000
+ /// @param a EList handle to modify element in.
1001
+ /// @param i Hidden index position of an element to modify.
1002
+ /// @param b Element value to be changed.
1003
+ /// @return ret A new elist handle
1004
+ function set(elist a, euint256 i, euint256 b) internal returns (elist ret) {
1005
+ return inco.listSet{value: inco.getEListFee(length(a), listTypeOf(a))}(a, euint256.unwrap(s(i)), euint256.unwrap(s(b)));
1006
+ }
1007
+
1008
+ /// @notice Replaces an element at plaintext index "i" (ebool variant). Reverts if out of range.
1009
+ /// @param a EList handle to modify element in.
1010
+ /// @param i Index position of element to modify.
1011
+ /// @param b Element value to be changed.
1012
+ /// @return ret A new elist handle
1013
+ function set(elist a, uint16 i, ebool b) internal returns (elist ret) {
1014
+ require(i < length(a), IndexOutOfRange(i, length(a)));
1015
+ return inco.listSet{value: inco.getEListFee(length(a), listTypeOf(a))}(a, euint256.unwrap(asEuint256(uint256(i))), ebool.unwrap(s(b)));
1016
+ }
1017
+
1018
+ /// @notice Replaces an element at plaintext index "i" (euint256 variant). Reverts if out of range.
1019
+ /// @param a EList handle to modify element in.
1020
+ /// @param i Index position of element to modify.
1021
+ /// @param b Element value to be changed.
1022
+ /// @return ret A new elist handle
1023
+ function set(elist a, uint16 i, euint256 b) internal returns (elist ret) {
1024
+ require(i < length(a), IndexOutOfRange(i, length(a)));
1025
+ return inco.listSet{value: inco.getEListFee(length(a), listTypeOf(a))}(a, euint256.unwrap(asEuint256(uint256(i))), euint256.unwrap(s(b)));
1026
+ }
1027
+
1028
+ /// @notice Return hidden element at some hidden position (ebool variant).
1029
+ /// @param a EList handle to get element from.
1030
+ /// @param i Hidden index position to get element at.
1031
+ /// @param defaultValue A default element value returned if index is out of range.
1032
+ /// @return ret A new handle for the element or the defaultValue
1033
+ function getOr(elist a, euint256 i, ebool defaultValue) internal returns (ebool ret) {
1034
+ return ebool.wrap(inco.listGetOr(a, euint256.unwrap(s(i)), ebool.unwrap(s(defaultValue))));
1035
+ }
1036
+
1037
+ /// @notice Return hidden element at some hidden position (euint256 variant).
1038
+ /// @param a EList handle to get element from.
1039
+ /// @param i Hidden index position to get element at.
1040
+ /// @param defaultValue A default element value returned if index is out of range.
1041
+ /// @return ret A new handle for the element or the defaultValue
1042
+ function getOr(elist a, euint256 i, euint256 defaultValue) internal returns (euint256 ret) {
1043
+ return euint256.wrap(inco.listGetOr(a, euint256.unwrap(s(i)), euint256.unwrap(s(defaultValue))));
1044
+ }
1045
+
1046
+ /// @notice Return hidden element at a known position as ebool.
1047
+ /// @param a EList handle to get element from.
1048
+ /// @param i Index position to get element at.
1049
+ /// @return ret Returns a handle for the element.
1050
+ function getEbool(elist a, uint16 i) internal returns (ebool ret) {
1051
+ return ebool.wrap(inco.listGet(a, i));
1052
+ }
1053
+
1054
+ /// @notice Return hidden element at a known position as euint256.
1055
+ /// @param a EList handle to get element from.
1056
+ /// @param i Index position to get element at.
1057
+ /// @return ret Returns a handle for the element.
1058
+ function getEuint256(elist a, uint16 i) internal returns (euint256 ret) {
1059
+ return euint256.wrap(inco.listGet(a, i));
1060
+ }
1061
+
1062
+ /// @notice Inserts a hidden element at a desired hidden position (ebool, hidden index).
1063
+ /// @param a An elist handle to insert into.
1064
+ /// @param i Hidden index position to insert at.
1065
+ /// @param b Element value to be inserted.
1066
+ /// @return ret A new elist handle with length len(a)+1.
1067
+ function insert(elist a, euint256 i, ebool b) internal returns (elist ret) {
1068
+ return inco.listInsert{value: inco.getEListFee(length(a) + 1, listTypeOf(a))}(a, euint256.unwrap(s(i)), ebool.unwrap(s(b)));
1069
+ }
1070
+
1071
+ /// @notice Inserts an ebool element at a known position. Reverts if out of range.
1072
+ /// @param a An elist handle to insert into.
1073
+ /// @param i Index position to insert at.
1074
+ /// @param b Element value to be inserted.
1075
+ /// @return ret A new elist handle with length len(a)+1.
1076
+ function insert(elist a, uint16 i, ebool b) internal returns (elist ret) {
1077
+ require(i < length(a), IndexOutOfRange(i, length(a)));
1078
+ return inco.listInsert{value: inco.getEListFee(length(a) + 1, listTypeOf(a))}(a, euint256.unwrap(asEuint256(uint256(i))), ebool.unwrap(s(b)));
1079
+ }
1080
+
1081
+ /// @notice Inserts a hidden element at a desired hidden position (euint256, hidden index).
1082
+ /// @param a An elist handle to insert into.
1083
+ /// @param i Hidden index position to insert at.
1084
+ /// @param b Element value to be inserted.
1085
+ /// @return ret A new elist handle with length len(a)+1.
1086
+ function insert(elist a, euint256 i, euint256 b) internal returns (elist ret) {
1087
+ return inco.listInsert{value: inco.getEListFee(length(a) + 1, listTypeOf(a))}(a, euint256.unwrap(s(i)), euint256.unwrap(s(b)));
1088
+ }
1089
+
1090
+ /// @notice Inserts a euint256 element at a known position. Reverts if out of range.
1091
+ /// @param a An elist handle to insert into.
1092
+ /// @param i Index position to insert at.
1093
+ /// @param b Element value to be inserted.
1094
+ /// @return ret A new elist handle with length len(a)+1.
1095
+ function insert(elist a, uint16 i, euint256 b) internal returns (elist ret) {
1096
+ require(i < length(a), IndexOutOfRange(i, length(a)));
1097
+ return inco.listInsert{value: inco.getEListFee(length(a) + 1, listTypeOf(a))}(a, euint256.unwrap(asEuint256(uint256(i))), euint256.unwrap(s(b)));
1098
+ }
1099
+
1100
+ /// @notice Concatenates two elists into one.
1101
+ /// @param a EList handle to be prepended
1102
+ /// @param b EList handle to be appended
1103
+ /// @return ret A new elist handle with length len(a)+len(b).
1104
+ function concat(elist a, elist b) internal returns (elist ret) {
1105
+ return inco.listConcat{value: inco.getEListFee(length(a) + length(b), listTypeOf(a))}(a, b);
1106
+ }
1107
+
1108
+ /// @notice Slices a list from plaintext start to plaintext end.
1109
+ /// @param a EList handle to be sliced
1110
+ /// @param start Starting index (inclusive).
1111
+ /// @param end End index (exclusive). Must be >= start and within bounds.
1112
+ /// @return ret A new sliced list with length "end-start".
1113
+ function slice(elist a, uint16 start, uint16 end) internal returns (elist ret) {
1114
+ require(end >= start, InvalidRange(start, end));
1115
+ require(end <= length(a), SliceOutOfRange(start, end, length(a)));
1116
+ require(start < length(a), SliceOutOfRange(start, end, length(a)));
1117
+ bytes32 defaultValue;
1118
+ if (ETypes.Uint256 == listTypeOf(a)) {
1119
+ defaultValue = euint256.unwrap(asEuint256(0));
1120
+ } else if (ETypes.Bool == listTypeOf(a)) {
1121
+ defaultValue = ebool.unwrap(asEbool(false));
1122
+ } else {
1123
+ revert UnsupportedListType(listTypeOf(a));
1124
+ }
1125
+ return inco.listSlice{value: inco.getEListFee(end - start, listTypeOf(a))}(a, euint256.unwrap(asEuint256(start)), end - start, defaultValue);
1126
+ }
1127
+
1128
+ /// @notice Slices at a hidden index with a specified length (euint256 default).
1129
+ /// @param a EList handle to be sliced.
1130
+ /// @param start Hidden starting index.
1131
+ /// @param len Length of the desired slice.
1132
+ /// @param defaultValue Default value if out of range.
1133
+ /// @return ret A new sliced list with length "len".
1134
+ function sliceLen(elist a, euint256 start, uint16 len, euint256 defaultValue) internal returns (elist ret) {
1135
+ return inco.listSlice{value: inco.getEListFee(len, listTypeOf(a))}(a, euint256.unwrap(s(start)), len, euint256.unwrap(s(defaultValue)));
1136
+ }
1137
+
1138
+ /// @notice Slices at a hidden index with a specified length (ebool default).
1139
+ /// @param a EList handle to be sliced.
1140
+ /// @param start Hidden starting index.
1141
+ /// @param len Length of the desired slice.
1142
+ /// @param defaultValue Default value if out of range.
1143
+ /// @return ret A new sliced list with length "len".
1144
+ function sliceLen(elist a, euint256 start, uint16 len, ebool defaultValue) internal returns (elist ret) {
1145
+ return inco.listSlice{value: inco.getEListFee(len, listTypeOf(a))}(a, euint256.unwrap(s(start)), len, ebool.unwrap(s(defaultValue)));
1146
+ }
1147
+
1148
+ /// @notice Creates a new list populated with ordered values from within range.
1149
+ /// @param start Start value of the range, inclusive.
1150
+ /// @param end End of the range, exclusive. Must be >= start.
1151
+ /// @return ret A new elist handle with length "end-start"
1152
+ function range(uint16 start, uint16 end, ETypes listType) internal returns (elist ret) {
1153
+ return inco.listRange{value: inco.getEListFee(end - start, listType)}(start, end, listType);
1154
+ }
1155
+
1156
+ /// @notice Deterministically shuffles elements within a list.
1157
+ /// @dev costs the inco fee
1158
+ /// @param a elist handle to be shuffled
1159
+ /// @return ret A new elist handle with elements shuffled
1160
+ function shuffle(elist a) internal returns (elist ret) {
1161
+ return inco.listShuffle{value: inco.getEListFee(length(a), listTypeOf(a))}(a);
1162
+ }
1163
+
1164
+ /// @notice A convenience function equivalent to range() followed by shuffle().
1165
+ /// @dev costs the inco fee
1166
+ /// @param start Start value of the range, inclusive.
1167
+ /// @param end End of the range, exclusive. Must be >= start.
1168
+ /// @return ret A new elist handle in random order with length "end-start".
1169
+ function shuffledRange(uint16 start, uint16 end, ETypes listType) internal returns (elist ret) {
1170
+ uint256 fee = inco.getEListFee(end - start, listType);
1171
+ elist rangeList = inco.listRange{value: fee}(start, end, listType);
1172
+ return inco.listShuffle{value: fee}(rangeList);
1173
+ }
1174
+
1175
+ /// @notice Reverses the order of elements in a list.
1176
+ /// @param a Elist handle to be reversed
1177
+ /// @return ret A new elist handle with elements in reverse order
1178
+ function reverse(elist a) internal returns (elist ret) {
1179
+ return inco.listReverse{value: inco.getEListFee(length(a), listTypeOf(a))}(a);
1180
+ }
1181
+
1182
+ /// @notice Returns the length of the list in plaintext. Pure function, no gas cost.
1183
+ /// @param a EList handle to read the length from
1184
+ /// @return len The length of the list
1185
+ function length(elist a) internal pure returns (uint16 len) {
1186
+ return inco.lengthOf(elist.unwrap(a));
1187
+ }
1188
+
1189
+ /// @notice verifyEListDecryption verifies elist decryption attestation and commitment proof. Each element can be either a pre-computed hash or a commitment-value pair.
1190
+ /// @param elistHandle The elist handle that was decrypted
1191
+ /// @param proofElements Array of proof elements. Each can provide either pairHash directly, or commitment+value to compute the pairHash
1192
+ /// @param proof The expected proof that should match keccak256 of all concatenated pair hashes
1193
+ /// @param signatures Array of signatures from attesters
1194
+ /// @return bool True if verification succeeds
1195
+ /// @dev For privacy, publish only pairHash. For transparency, publish commitment+value. Can mix both in the same array.
1196
+ function verifyEListDecryption(elist elistHandle, ElementAttestationWithProof[] memory proofElements, bytes32 proof, bytes[] memory signatures) internal view returns (bool) {
1197
+ return inco.incoVerifier().isValidEListDecryptionAttestation(elist.unwrap(elistHandle), proofElements, proof, signatures);
1198
+ }
1199
+
1200
+ /// @notice Checks a decryption attestation for an encrypted bool against an expected plaintext value
1201
+ /// @param handle The encrypted handle
1202
+ /// @param expected The expected plaintext value
1203
+ /// @param decryption The decryption attestation to verify
1204
+ /// @param signatures The covalidator signatures for the attestation
1205
+ /// @dev Reverts if the handle doesn't match, the decrypted value doesn't match the expected value, or the attestation is invalid
1206
+ function requireEqual(ebool handle, bool expected, DecryptionAttestation memory decryption, bytes[] memory signatures) internal view {
1207
+ require(ebool.unwrap(handle) == decryption.handle, HandleMismatch());
1208
+ require(asBool(decryption.value) == expected, UnexpectedDecryptedValue());
1209
+ require(inco.incoVerifier().isValidDecryptionAttestation(decryption, signatures), InvalidTEEAttestation());
1210
+ }
1211
+
1212
+ /// @notice Checks a decryption attestation for an encrypted uint256 against an expected plaintext value
1213
+ /// @param handle The encrypted handle
1214
+ /// @param expected The expected plaintext value
1215
+ /// @param decryption The decryption attestation to verify
1216
+ /// @param signatures The covalidator signatures for the attestation
1217
+ /// @dev Reverts if the handle doesn't match, the decrypted value doesn't match the expected value, or the attestation is invalid
1218
+ function requireEqual(euint256 handle, uint256 expected, DecryptionAttestation memory decryption, bytes[] memory signatures) internal view {
1219
+ require(euint256.unwrap(handle) == decryption.handle, HandleMismatch());
1220
+ require(uint256(decryption.value) == expected, UnexpectedDecryptedValue());
1221
+ require(inco.incoVerifier().isValidDecryptionAttestation(decryption, signatures), InvalidTEEAttestation());
1222
+ }
942
1223
  }
@@ -106,6 +106,9 @@ abstract contract AdvancedAccessControl is
106
106
  /// @param activeSessionNonce The sharer's current active session nonce
107
107
  error InvalidVoucherSessionNonce(bytes32 providedSessionNonce, bytes32 activeSessionNonce);
108
108
 
109
+ /// @notice Thrown when a voucher's verifyingContract address is the zero address
110
+ error InvalidVerifyingContract();
111
+
109
112
  /// @notice Checks if an account is allowed to access a handle using a signed voucher proof
110
113
  /// @dev Intended for simulation/off-chain calls. Not a view function as it calls external contracts.
111
114
  /// Verification steps:
@@ -118,6 +121,7 @@ abstract contract AdvancedAccessControl is
118
121
  /// @param proof The allowance proof containing voucher, signature, and requester data
119
122
  /// @return True if access is allowed, false or reverts otherwise
120
123
  function isAllowedWithProof(bytes32 handle, address account, AllowanceProof memory proof) public returns (bool) {
124
+ require(proof.voucher.verifyingContract != address(0), InvalidVerifyingContract());
121
125
  require(
122
126
  IBaseAccessControlList(incoLightningAddress).isAllowed(handle, proof.sharer),
123
127
  SharerNotAllowedForHandle(handle, proof.sharer)
@@ -150,12 +154,13 @@ abstract contract AdvancedAccessControl is
150
154
  }
151
155
 
152
156
  /// @notice Invalidates all previously signed vouchers by updating the session nonce
153
- /// @dev Generates a new random nonce using the caller's address and block.prevrandao.
157
+ /// @dev Generates a new random nonce using the caller's address, block.prevrandao, block.number, block.timestamp, and an additional random value.
154
158
  /// Any vouchers signed with the previous nonce become invalid immediately.
155
159
  /// Call this if you suspect voucher compromise or want to revoke all delegations.
156
- function updateActiveVouchersSessionNonce() external {
160
+ /// @param salt An additional random value to ensure nonce uniqueness (e.g., from an off-chain source)
161
+ function updateActiveVouchersSessionNonce(bytes32 salt) external {
157
162
  getAacStorage().activeVouchersSessionNonce[msg.sender] =
158
- keccak256(abi.encodePacked(msg.sender, block.prevrandao));
163
+ keccak256(abi.encodePacked(msg.sender, block.prevrandao, block.number, block.timestamp, salt));
159
164
  }
160
165
 
161
166
  }
@@ -137,22 +137,6 @@ abstract contract BaseAccessControlList is
137
137
  return isAllowedTransient;
138
138
  }
139
139
 
140
- /// @notice Clears all transient storage entries.
141
- /// @dev Should be called at the end of a transaction to reset transient permissions.
142
- /// Iterates through all stored keys and clears them.
143
- function cleanTransientStorage() external {
144
- assembly {
145
- let length := tload(0)
146
- tstore(0, 0)
147
- let lengthPlusOne := add(length, 1)
148
- for { let i := 1 } lt(i, lengthPlusOne) { i := add(i, 1) } {
149
- let handle := tload(i)
150
- tstore(i, 0)
151
- tstore(handle, 0)
152
- }
153
- }
154
- }
155
-
156
140
  /// @notice Claims access to a handle using a signed allowance proof.
157
141
  /// @dev Verifies the proof via IncoVerifier and grants persistent access if valid.
158
142
  /// @param handle The encrypted handle to claim access to.
@@ -13,6 +13,6 @@ interface IAdvancedAccessControl is IVoucherEip712Checker {
13
13
 
14
14
  function isAllowedWithProof(bytes32 handle, address account, AllowanceProof memory proof) external returns (bool);
15
15
  function getActiveVouchersSessionNonce(address account) external view returns (bytes32);
16
- function updateActiveVouchersSessionNonce() external;
16
+ function updateActiveVouchersSessionNonce(bytes32 salt) external;
17
17
 
18
18
  }
@@ -2,14 +2,15 @@
2
2
  pragma solidity ^0.8;
3
3
 
4
4
  import {IVerifierAddressGetter} from "../../primitives/interfaces/IVerifierAddressGetter.sol";
5
+ import {IEventCounter} from "../../primitives/interfaces/IEventCounter.sol";
5
6
  import {AllowanceProof} from "../AdvancedAccessControl.types.sol";
6
7
 
7
- interface IBaseAccessControlList is IVerifierAddressGetter {
8
+ interface IBaseAccessControlList is IVerifierAddressGetter, IEventCounter {
8
9
 
9
10
  function allow(bytes32 handle, address account) external;
11
+ function reveal(bytes32 handle) external;
10
12
  function allowTransient(bytes32 handle, address account) external;
11
13
  function allowedTransient(bytes32 handle, address account) external view returns (bool);
12
- function cleanTransientStorage() external;
13
14
  function persistAllowed(bytes32 handle, address account) external view returns (bool);
14
15
  function isAllowed(bytes32 handle, address account) external view returns (bool);
15
16
  function claimHandle(bytes32 handle, AllowanceProof memory proof) external;
@@ -88,6 +88,21 @@ contract TestAdvancedAccessControl is IncoTest {
88
88
  incoVerifier = inco.incoVerifier();
89
89
  }
90
90
 
91
+ function testAdvancedSharingWithInvalidVerifyingContract() public {
92
+ AllowanceVoucher memory invalidSessionVoucher = AllowanceVoucher({
93
+ sessionNonce: bytes32(0),
94
+ verifyingContract: address(0),
95
+ callFunction: SessionVerifier.canUseSession.selector,
96
+ sharerArgData: abi.encode(Session({decrypter: bob, expiresAt: block.timestamp + 1 days}))
97
+ });
98
+ AllowanceProof memory bobsProof = getBobsProof(invalidSessionVoucher);
99
+ vm.expectRevert(abi.encodeWithSelector(AdvancedAccessControl.InvalidVerifyingContract.selector));
100
+ incoVerifier.isAllowedWithProof(secretHandle, bob, bobsProof);
101
+ vm.prank(bob);
102
+ vm.expectRevert(abi.encodeWithSelector(AdvancedAccessControl.InvalidVerifyingContract.selector));
103
+ inco.claimHandle(secretHandle, bobsProof);
104
+ }
105
+
91
106
  function testAdvancedSharingWithSession() public {
92
107
  SessionVerifier sessionVerifier = new SessionVerifier("");
93
108
  assertFalse(inco.isAllowed(secretHandle, bob), "bob should't be allowed on secret yet");
@@ -134,7 +149,9 @@ contract TestAdvancedAccessControl is IncoTest {
134
149
  );
135
150
  incoVerifier.isAllowedWithProof(secretHandle, bob, invalidBobProof);
136
151
  vm.prank(alice);
137
- incoVerifier.updateActiveVouchersSessionNonce();
152
+ bytes32 salt = keccak256(abi.encodePacked("some random value", block.timestamp));
153
+ // update the session nonce to invalidate all previous vouchers
154
+ incoVerifier.updateActiveVouchersSessionNonce(salt);
138
155
  bytes32 alicesNewNonce = incoVerifier.getActiveVouchersSessionNonce(alice);
139
156
  // previously valid voucher should now be invalid
140
157
  vm.expectRevert(
@@ -53,30 +53,6 @@ contract TestBaseAccessControl is BaseAccessControlList, IncoTest {
53
53
  inco.allowTransient(handle, carol);
54
54
  }
55
55
 
56
- // ============ cleanTransientStorage Tests ============
57
-
58
- function testCleanTransientStorage() public {
59
- euint256 secret1 = inco.asEuint256(100);
60
- euint256 secret2 = inco.asEuint256(200);
61
- bytes32 handle1 = euint256.unwrap(secret1);
62
- bytes32 handle2 = euint256.unwrap(secret2);
63
-
64
- // Grant transient access
65
- inco.allowTransient(handle1, bob);
66
- inco.allowTransient(handle2, carol);
67
-
68
- // Verify transient access is granted
69
- assertTrue(inco.allowedTransient(handle1, bob));
70
- assertTrue(inco.allowedTransient(handle2, carol));
71
-
72
- // Clean transient storage
73
- inco.cleanTransientStorage();
74
-
75
- // Transient access should be revoked
76
- assertFalse(inco.allowedTransient(handle1, bob));
77
- assertFalse(inco.allowedTransient(handle2, carol));
78
- }
79
-
80
56
  // ============ allowedTransient Direct Call Tests ============
81
57
 
82
58
  function testAllowedTransient_DirectCall() public {
@@ -227,25 +203,6 @@ contract TestBaseAccessControl is BaseAccessControlList, IncoTest {
227
203
  assertEq(inco.isAllowed(handle, bob), expectedAllowed);
228
204
  }
229
205
 
230
- /// @dev Fuzz test that cleaning transient storage removes transient access
231
- function testFuzzCleanTransientStorageRemovesAccess(bytes32 randomSeed) public {
232
- // Create a unique handle
233
- euint256 secret = inco.asEuint256(uint256(randomSeed));
234
- bytes32 handle = euint256.unwrap(secret);
235
-
236
- // Grant transient access
237
- inco.allowTransient(handle, bob);
238
- assertTrue(inco.allowedTransient(handle, bob));
239
- assertTrue(inco.isAllowed(handle, bob));
240
-
241
- // Clean transient storage
242
- inco.cleanTransientStorage();
243
-
244
- // Transient access should be revoked
245
- assertFalse(inco.allowedTransient(handle, bob));
246
- assertFalse(inco.isAllowed(handle, bob));
247
- }
248
-
249
206
  /// @dev Fuzz test multiple accounts with different access levels
250
207
  function testFuzzMultipleAccountsAccessLevels(bytes32 randomSeed) public {
251
208
  euint256 secret = inco.asEuint256(uint256(randomSeed));