zk-FOAKs Algorithm

The Protocol of ZK-FOAKS is as follows:

Public Input: The evaluation point x, parsed as a tensor product r = r0 ⊗ r1;
Private Input: polynomial p with coefficient w
C: a [n,k,d]-linear code
EC: the encoding function
N = k×k

function Commit(p):
    Parse w as a k×k matrix. 
    The prover computes the tensor code encoding C1, C2.
    (Here C1 is a k×n matrix and C2 is a n×n matrix.)
    for i ∈ [n]:
        Compute the Merkle tree root Root_i = Merkle.Commit(C2[:, i]).
    Compute a Merkle tree root R = Merkle.Commit([Root_0, ..., Root_(n−1)]).
    return R

function Foaks.Prove(ϕ,x,R):
    The prover receives v0∈F^k from the verifier.
    c1 = Sum r0[i]C1[i] from i = 0 to k-1
    y1 = Sum r0[i]w[i] from i = 0 to k-1
    R(c1) = Merkel.Commit(c1)
    cv0 = Sum v0[i]C1[i] from i = 0 to k-1
    yv0 = Sum v0[i]w[i] from i = 0 to k-1
    R(v0) = Merkel.Commit(cv0)
    The prover sends R(c1), R(v0), and  y=<y1,r1> to the verifier.
    The verifier randomly samples t∈[n] indexs as an array J and sends it to the prover.
    The verifier randomly samples another index set I⊆[k] (|I|=t) and sends it to the prover.
    The prover calls ZK.P on C_CS, yield the proof π, and sends C2[I[j],idx] ∀idx∈J, c1[I[j]], cv0[I[j]], and π to the verifier.
    The prover sends the Merkle tree proofs of C2[I[j],idx] ∀idx∈J under Root_idx.
    The prover sends the Merkle tree proofs of Root_idx ∀idx∈J under R.
    The prover sends the Merkle tree proofs of c1[I[j]], cv0[I[j]] under R(c1) and R(cv0).

function Foaks.Verify(π, x, y=ϕ(x), R):
    The verifier calls ZK.V on C_CS.
    The verifier checks the Merkel tree proofs of C2[I[j],idx] ∀idx∈J.
    The verifier checks the Merkel tree proofs of Root_idx ∀idx∈J using R.
    The verifier checks the Merkel tree proofs of c1[I[j]], cv0[I[j]] using R(c1) and R(cv0).
    Return (all checks pass) ? ACCEPT : REJECT

Note: Here, ZK=(ZK.P, ZK.V) can be any zero-knowledge argument protocol. C_CS is the Code Switching Statement as follows:

Witness: yv0, y1, C1[:, idx] ∀idx∈J in the above protocol
Public input: v0, r0, r1, y
Public information: J and I are chosen by the verifier

Encode cv0 := EC(yv0), c1 := EC(y1)

for idx∈J:
    Encode C2[:, idx] := EC(C1[:, idx])

for idx∈J:
    Proximity check: check if cv0[idx] == <v0, C1[:, idx]>
    Consistency check: check if c1[idx] == <r0, C1[:, idx]>

Tensor product check: check if <r1, y1> == y

Encoder check:
for 0 ≤ j < |I|:
    Output c1[I[j]], cv0[I[j]].
    for idx∈J:
        Output C2[I[j], idx]

Last updated