Before you start
Import theePreview library:
Important: Fee Payments and Access Control
Fee Payments: Most elist operations that consume encrypted inputs require paying fees. When calling
ePreview.newEList(), ensure msg.value >= inco.getFee() * ciphertextCount. Operations like shuffle() and shuffledRange() also require fee payment.Access Control: After creating or modifying an elist, you must explicitly grant access permissions using
inco.allow() to allow addresses to decrypt the list contents. Always allow both the contract and the user who needs access:Creating new empty EList
newEList(type) creates a new empty list and returns a new elist handle. Type must be specified ahead of time and can not be changed.
Here is an example of how to create a new EList holding euint256 values:
Note: Each elist handle is IMMUTABLE, so a handle will forever point to a particular list of values. Any operation on a list will return a new handle pointing to a new list, leaving the original list unchanged.
- ETypes listType - Type of each element in the list. This can not be changed
- Elist - a new elist handle
Creating new EList from existing handles
newEList(handles, type) creates a new list from existing list of handles and returns a new elist handle. Type must be specified ahead of time and can not be changed.
Handles type must match the type of the list container, otherwise it will revert.
Here is an example of how to create a new EList from existing euint256 handles:
- bytes32[] handles - An array of handles to create a new list from
- ETypes listType - Type of each element in the list. This can not be changed and must match the type of each handle in the array.
- Elist - A new elist handle
Length
length(list) returns the length of the list in plaintext. It’s a pure function that doesn’t require any gas to call.
Note: It is IMPORTANT to keep in mind that the length of the elist is ALWAYS PUBLIC and encoded inside the returning handle itself. It’s an intentional design choice to make contract behavior more predictable at a cost of leaking the length of the list, because it can (for the most part) always be predicted by looking at history of on-chain operations.
- elist list - list to read length from
- uint16 len - length of the list in plaintext
ListTypeOf
listTypeOf(list) returns the type of elements contained in the list. It’s a view function that doesn’t require any gas to call.
- elist list - list to read type from
- ETypes - the type of elements in the list (e.g.,
ETypes.Uint256,ETypes.Bool)
Creating new EList from user inputs
Sometimes it’s desired to create an elist from user inputs directly, like from a javascript dApp.newEList(inputs, type, user) can take an array of user encrypted ciphertexts and returns a new elist handle. Expected type must be specified ahead of time and can not be changed.
Handles type must match the type of the list container, otherwise it will revert.
Here is a complete example of how to create a new EList from user encrypted inputs:
- bytes[] ciphertexts - An array of encrypted user inputs to create a new list from
- ETypes listType - Expected type of each element in the list. This can not be changed and must match the type of each handle in the array.
- address user - Address of the owner of the inputs, used to decrypt ciphertexts.
- elist - A new elist handle
Append
append(list, value) appends an euint256 or ebool element type at the end of an array, returning a new modified list handle.
Example usage:
- elist list - An elist handle to append to
- euint256/ebool value - Element value to be appended to the list. Must match the elist type.
- elist - A new elist handle
Insert
insert(list, i, value) inserts a hidden element at a desired hidden position, returns a new modified list. Index can be both plaintext or encrypted.
Example usage:
- elist A - An elist handle to insert to
- euint256/uint256 i - Index position to insert at, can be both encrypted or plaintext.
- euint256/ebool B - Element value to be inserted to the list. Must match the elist type.
- Elist - A new elist handle
Get
getEuint256(list, index) and getEbool(list, index) return the hidden element at a plaintext position. These methods have separate names due to Solidity function overloading limitations.
Example usage:
- elist list - elist handle to get element from
- uint16 index - Plaintext index position to get element at
- euint256 or ebool - The encrypted value at the specified index
GetOr
getOr(list, i, default) return hidden element at hidden position. Index can be either encrypted or plaintext.
Returns a handle to the hidden element if the index is within range, otherwise returns the default value.
Example usage:
- elist list - elist handle to get element at
- euint256/uint256 index - Index position to get element at. Can be either plaintext or encrypted.
- euint256/ebool default - A default element value to be returned if index is out of range. Must match the elist type.
- euint256/ebool - The encrypted value at the specified index, or the default value if out of range
Set
set(list, i, value) replaces an element at hidden index and returns a new modified list. Index can be either plaintext or encrypted.
Example usage:
- elist A - elist handle to modify element in
- euint256/uint256 i - index position of element to modify. Can be either plaintext or encrypted.
- euint256/ebool B - element value to be changed if index is within range. Element will be appended to the list if the index is out of range. Must match the elist type.
- Elist - a new elist handle
Concat
concat(list_a, list_b) concatenates two elists into one, returns a new concatenated elist. The length of the new list will be length(list1)+length(list2)
Example usage:
- elist list_a - elist handle to be prepended
- elist list_b - elist handle to be appended
- Elist - a new elist handle containing elements from both A and B
Slice
slice(list, start, end) is like in any other language that takes in start and end both in plaintext. Returns a new sliced list of length “end-start”.
If start and end are out of bounds, it will revert. The end index must be greater than the start index.
Example usage:
- elist A - elist handle to be sliced
- uint16 start - Start index of the slice, in plaintext.
- uint16 end - End index of the slice, in plaintext. Must be greater than start and within the bounds of the list length.
- Elist - a new sliced list with a new length of “end-start”
SliceLen
sliceLen(list, E(start), len, defaultValue) is a variant of slice() but allows to slice at some hidden index specifying a length instead of end position. Returns a new sliced list of the specified length.
Example usage:
- elist list - elist handle to be sliced
- euint256 start - Encrypted start index of the slice
- uint16 len - Length of the desired slice
- euint256/ebool defaultValue - Default value to use if start position is out of bounds. Must match the elist type.
- elist - a new sliced list with the specified length
Range
range(start, end) creates a new list (or a “set”) and populates it with ordered values from within range. The length of the new list will be equal to “end-start”.
Example usage:
- uint16 start - Start value of the range, inclusive.
- uint16 end - End of the range, exclusive. Must be greater than start.
- Elist - a new elist handle containing elements from start to end-1 with the length of “end-start”
Reverse
reverse(list) reverses elements in a list, first element becomes last, and so on.
Example usage:
- elist A - elist handle to be reversed
- Elist - a new elist handle with elements in reverse order
Shuffle
shuffle(list) deterministically shuffles elements within a list, returning a new shuffled list with the same length. This operation requires fee payment.
Example usage:
- elist list - elist handle to be shuffled
- elist - a new elist handle with elements shuffled where each element is equally likely to be in any position in the new list.
ShuffledRange
shuffledRange(start, end) is a convenience function combining range() and shuffle() from example above into one function. It creates a range of elements from start to end, unlike range() the resulting elist is unordered and completely random. This operation requires fee payment.
Example usage:
- uint16 start - Start value of the range, inclusive.
- uint16 end - End of the range, exclusive. Must be greater than start.
- elist - a new elist handle containing elements from start to end-1 with the length of “end-start” in a random order.