EList
The Inco Lightning SDK provides encrypted lists (EList) — confidential, immutable, homogeneous dynamic arrays of Euint128 or Ebool values. Like the scalar operations, every elist operation is a cross-program invocation that returns a new handle; the covalidator network performs the actual list computation off-chain.
The EList, EListType types are documented in Types. Element values are passed as raw u128 handles (Euint128.0 / Ebool.0), and encrypted indices are Euint128.
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.
Constructor Operations
Read Operations
Modifying Operations
Operations that produce a new list return a newEList handle.
Creating new EList from existing handles
new_elist_from_handles(handles, list_type) creates a new list from an 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.
Creating new EList from user inputs
Sometimes it’s desired to create an elist from user inputs directly, like from a javascript dApp.new_elist_from_inputs(inputs, list_type, user) takes 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.
Length and ListType
The length and element type of a list travel inside theEList handle itself and are read directly from the struct fields — no CPI is required.
Note: It is IMPORTANT to keep in mind that the length of the elist is ALWAYS PUBLIC and encoded inside the handle itself. It’s an intentional design choice to make program 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.
Append
list_append(list, value) appends a Euint128 or Ebool element at the end of a list, returning a new modified list handle.
Insert
list_insert(list, index, value) inserts a hidden element at an encrypted position, returning a new modified list.
Get
list_get(list, index) returns the hidden element at a plaintext position as a raw u128 handle.
GetOr
list_get_or(list, index, default_value) returns the hidden element at an encrypted position. Returns a handle to the hidden element if the index is within range, otherwise returns the default value.
Set
list_set(list, index, value) replaces an element at an encrypted index and returns a new modified list.
Concat
list_concat(lhs, rhs) concatenates two elists into one and returns a new concatenated elist. The length of the new list will be length(lhs) + length(rhs).
Slice
list_slice(list, start, len, default_value) slices at a hidden start position for a specified length, returning a new sliced list of the specified length.
Range
list_range(start, end, list_type) creates a new list (or a “set”) and populates it with ordered values from within the range. The length of the new list will be equal to end - start.
Reverse
list_reverse(list) reverses elements in a list — the first element becomes last, and so on.
Shuffle
list_shuffle(list, counter) deterministically shuffles elements within a list, returning a new shuffled list with the same length. The caller-supplied counter is mixed into the operation as a nonce.
Handles are deterministically derived from operations, so the same operation on the same list with the same inputs always produces the same handle.