Skip to content

zorch.spartan.zerocheck

Outer Spartan zerocheck role implementations.

ZerocheckClaim dataclass

Public claim that the outer relation vanishes over this many variables.

Source code in zorch/spartan/zerocheck.py
28
29
30
31
32
@dataclass(frozen=True)
class ZerocheckClaim:
    """Public claim that the outer relation vanishes over this many variables."""

    rounds: int

ZerocheckWitness dataclass

The three multilinear factor tables witnessing ZerocheckClaim.

Source code in zorch/spartan/zerocheck.py
35
36
37
38
39
40
41
@dataclass(frozen=True)
class ZerocheckWitness:
    """The three multilinear factor tables witnessing ``ZerocheckClaim``."""

    az: Array
    bz: Array
    cz: Array

RowEvaluationClaim dataclass

Claimed (Az, Bz, Cz) evaluations at the reduced row point.

Source code in zorch/spartan/zerocheck.py
44
45
46
47
48
49
@dataclass(frozen=True)
class RowEvaluationClaim:
    """Claimed ``(Az, Bz, Cz)`` evaluations at the reduced row point."""

    point: Array
    values: Array

OuterProof dataclass

The outer sumcheck messages and terminal (Az, Bz, Cz) values.

Source code in zorch/spartan/zerocheck.py
52
53
54
55
56
57
@dataclass(frozen=True)
class OuterProof:
    """The outer sumcheck messages and terminal ``(Az, Bz, Cz)`` values."""

    sumcheck: Any
    claims: Array

OuterProver

Bases: ProverStage[ZerocheckClaim, ZerocheckWitness, RowEvaluationClaim, OuterProof]

Prove zerocheck conditional on a row-evaluation claim.

Source code in zorch/spartan/zerocheck.py
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
class OuterProver(
    ProverStage[ZerocheckClaim, ZerocheckWitness, RowEvaluationClaim, OuterProof]
):
    """Prove zerocheck conditional on a row-evaluation claim."""

    def __init__(
        self,
        *,
        sumcheck: (
            ProverStage[EqSumClaim, EqPolyWitness, EvaluationClaim, Any] | None
        ) = None,
        challenges: ChallengePolicy,
    ) -> None:
        self.challenges = challenges
        self.sumcheck = sumcheck or EqPolyProver(
            ZerocheckSummand(), challenges=challenges
        )

    def prove(
        self,
        claim: ZerocheckClaim,
        witness: ZerocheckWitness,
        transcript: Transcript,
    ) -> ProveResult[RowEvaluationClaim, OuterProof]:
        az, bz, cz = witness.az, witness.bz, witness.cz
        rounds = log2_strict_usize(az.shape[0])
        if rounds != claim.rounds:
            raise ValueError(
                f"claim expects {claim.rounds} outer rounds, witness needs {rounds}"
            )
        tau, transcript = _sample_tau(claim.rounds, transcript, self.challenges)
        factors = fnp.stack([az, bz, cz])
        zero = fnp.zeros((), tau.dtype)
        reduced = self.sumcheck.prove(
            EqSumClaim(tau, zero, claim.rounds),
            EqPolyWitness(factors),
            transcript,
        )
        point = reduced.reduced_claim.point
        values = fnp.stack(
            [eval_mle(az, point), eval_mle(bz, point), eval_mle(cz, point)]
        )
        transcript = reduced.transcript.observe(values)
        return ProveResult(
            RowEvaluationClaim(point, values),
            OuterProof(reduced.reduction_proof, values),
            transcript,
        )

OuterVerifier

Bases: VerifierStage[ZerocheckClaim, RowEvaluationClaim, OuterProof]

Verify zerocheck conditional on a row-evaluation claim.

Source code in zorch/spartan/zerocheck.py
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
class OuterVerifier(VerifierStage[ZerocheckClaim, RowEvaluationClaim, OuterProof]):
    """Verify zerocheck conditional on a row-evaluation claim."""

    def __init__(
        self,
        *,
        sumcheck: VerifierStage[EqSumClaim, EvaluationClaim, Any] | None = None,
        challenges: ChallengePolicy,
    ) -> None:
        self.challenges = challenges
        self.sumcheck = sumcheck or EqPolyVerifier(
            ZerocheckSummand(), challenges=challenges
        )

    def verify(
        self,
        claim: ZerocheckClaim,
        reduction_proof: OuterProof,
        transcript: Transcript,
    ) -> VerifyResult[RowEvaluationClaim]:
        tau, transcript = _sample_tau(claim.rounds, transcript, self.challenges)
        # Both roles derive the source-claim field from the public challenge.
        zero = fnp.zeros((), tau.dtype)
        reduced = self.sumcheck.verify(
            EqSumClaim(tau, zero, claim.rounds),
            reduction_proof.sumcheck,
            transcript,
        )
        point = reduced.reduced_claim.point
        final_value = reduced.reduced_claim.value
        transcript = reduced.transcript.observe(reduction_proof.claims)
        va, vb, vc = reduction_proof.claims
        ok = reduced.ok & (final_value == eval_eq(tau, point) * (va * vb - vc))
        return VerifyResult(
            RowEvaluationClaim(point, reduction_proof.claims), transcript, ok
        )