Lookup
In this part, we describe how to produce a witness to the lookup argument described here.
We have a pair of arrays, A and S of the same length m, in our case S can be assumed to be public and already sorted, and A is a shared array, which is known to be a subset of S (with repetitions). The witness consists of a new pair of arrays, _A, _S, satisfing the following condition: either _A[i] == _S[i], or _A[i] == _A[i-1]. The second condition can not hold for i == 0.
The arrays also are constrained by requirement that A is a permutation of _A, and S is a permutation of _S.
The non-MPC algorithm does the following:
- Sort
A, this will be_A. Call an indexi"initial" if eitheri == 0, or_A[i] != _A[i-1]. - For each initial element, find the corresponding
jsuch that_A[i] = S[j], and set_S[i] = S[j]. - Fill in the rest of values.
Searching for elements in MPC is not very efficient, so we use a slightly different strategy:
- Consider a disjoint union (we will add an additional parameter to remember from which array an element came from, so
T[i].valuerepresents the actual value, andT[i].extis either0or1). Sort in place by value. - Introduce a new bit flag:
T[i].paired, which is set as(T[i].ext == 1 & T[i-1].ext == 0) | (T[i].ext == 0 & T[i+1].ext == 1). - Sort in place by
ext>1-paired, strip off additional introduced fields. - Create a new array of tuples
pairs[i] = (T[i], T[m+i]). - Sort this array by the first element of the tuple in place, set
(_A[i], _S[i]) = pairs[i].
Why this works:
First, we sort by value, so obtain the batches of the same value coming from A, intercepted by increasing values coming from S. The field paired is set to 1 exactly for one element from A and corresponding element from S (also, in this phase we could check whether lookup is incorrect if we wanted, which amounts to a situation where the neighboring elements with ext == 0 have different values).
Now, we order by ext, splitting the arrays back and there move the elements of paired == 1 kind to the left of their respective halves. Upon pairing, and sorting by the first element of the tuple, each paired element of A becomes first in a batch of the elements of equal value (because the sort was stable).