- Let and suppose a verifier has all evaluations for .
- The domain of has size .
- Given for all and a -dimensional vector , the verifier must efficiently evaluate .
Streaming Interactive Proofs
- See the paper Verifying Computations with Streaming Interactive Proofs
- The verifier can compute in time and space by streaming the inputs for all .
- The order of the inputs does not matter
- can calculate the sum
with a recursive algorithm.
- Begin by initializing the accumulator to 0: . Then with each entry, add the next term to the accumulator
- With this approach, the verifier only needs to store the value and the current value of as it iterates through values of . is a -dimensional vector of elements of and , so the algorithm's space usage is field elements or
- The verifier runs through each of the values in , each time evaluating the -term Lagrange basis polynomial
so operations in are run to compute the full sum, resulting in a runtime of or .
Implementation
function getMultilinearLagrange(message: string, x: Field[]): Field {
const n = message.length;
if (n === 0) {
throw Error("Dataset cannot be empty.");
}
// dimension of hypercube required to encode n entries
// 2^d must be at least as large as n const d = Math.ceil(Math.log2(n));
// accumulator for result as terms in summation are evaluated
let accumulator = Field(0);
// ordered list of n vertices being interpolated
const interpolatingSet = generateBinaryVertices(d);
let lagrangeBasisAtInput;
// sum over all vertices in the d dimensional hypercube to create the interpolating polynomial
// O(n) // todo - can we sum over n entries of the message instead of 2^d vertices?
for (let i = 0; i < interpolatingSet.length; i++) {
// obtain field representation of ascii character in message
// 2^d will likely be larger than n, right-pad the message with zeroes const coefficient =
i >= message.length ? Field(0) : Field(asciiToNumber(message[i]));
lagrangeBasisAtInput = getMultilinearLagrangeBasisAt(
interpolatingSet[i],
interpolatingSet,
x,
);
// Add the current term (coefficient * current basis) to the result
accumulator = accumulator.add(coefficient.mul(lagrangeBasisAtInput));
}
return accumulator;
}
function getMultilinearLagrangeBasisAt(
w: number[],
interpolatingSet: number[][],
x: Field[],
): Field {
if (
w.length !== interpolatingSet[0].length ||
x.length !== interpolatingSet[0].length
)
throw Error(
`Vectors w: ${w} and x: ${x} must be ${interpolatingSet.length}-dimensional`,
);
let accumulator = Field(1);
// lagrange basis polynomial is a product over all entries in the vertex w
for (let i = 0; i < w.length; i++) {
accumulator = accumulator.mul(
x[i].mul(w[i]).add(
Field(1)
.sub(x[i])
.mul(1 - w[i]),
),
);
}
return accumulator;
}