Skip to content

Commit

Permalink
WIP PLONK
Browse files Browse the repository at this point in the history
  • Loading branch information
ivokub committed Nov 8, 2023
1 parent e40ddc2 commit 2116255
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 73 deletions.
122 changes: 61 additions & 61 deletions std/recursion/plonk/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import (
fiatshamir "github.com/consensys/gnark/std/fiat-shamir"
"github.com/consensys/gnark/std/hash"
"github.com/consensys/gnark/std/math/emulated"
"github.com/consensys/gnark/std/math/emulated/emparams"
"github.com/consensys/gnark/std/recursion"
)

type Proof[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2ElementT] struct {
type Proof[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT] struct {
// Commitments to the solution vectors
LRO [3]kzg.Commitment[G1El]
// Commitment to Z, the permutation polynomial
Expand All @@ -35,17 +35,17 @@ type Proof[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2ElementT]
Bsb22Commitments []kzg.Commitment[G1El]

// Batch opening proof of h1 + zeta*h2 + zeta**2h3, linearizedPolynomial, l, r, o, s1, s2, qCPrime
BatchedProof kzg.BatchOpeningProof[S, G1El]
BatchedProof kzg.BatchOpeningProof[FR, G1El]

// Opening proof of Z at zeta*mu
ZShiftedOpening kzg.OpeningProof[S, G1El]
ZShiftedOpening kzg.OpeningProof[FR, G1El]
}

func ValueOfProof[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2ElementT](proof backend_plonk.Proof) (Proof[S, G1El, G2El], error) {
var ret Proof[S, G1El, G2El]
func ValueOfProof[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT](proof backend_plonk.Proof) (Proof[FR, G1El, G2El], error) {
var ret Proof[FR, G1El, G2El]
var err error
switch r := any(&ret).(type) {
case *Proof[sw_bls12377.Scalar, sw_bls12377.G1Affine, sw_bls12377.G2Affine]:
case *Proof[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine]:
tProof, ok := proof.(*plonkbackend_bls12377.Proof)
if !ok {
return ret, fmt.Errorf("expected sw_bls12377.Proof, got %T", proof)
Expand Down Expand Up @@ -74,11 +74,11 @@ func ValueOfProof[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2Ele
}
}
// TODO: actually we compute the opening point later. Maybe we can precompute it here and later assert its correctness?
r.BatchedProof, err = kzg.ValueOfBatchOpeningProof[sw_bls12377.Scalar, sw_bls12377.G1Affine]([]fr_bls12377.Element{}, tProof.BatchedProof)
r.BatchedProof, err = kzg.ValueOfBatchOpeningProof[sw_bls12377.ScalarField, sw_bls12377.G1Affine]([]fr_bls12377.Element{}, tProof.BatchedProof)
if err != nil {
return ret, fmt.Errorf("batch opening proof value assignment: %w", err)
}
r.ZShiftedOpening, err = kzg.ValueOfOpeningProof[sw_bls12377.Scalar, sw_bls12377.G1Affine](fr_bls12377.One(), tProof.ZShiftedOpening)
r.ZShiftedOpening, err = kzg.ValueOfOpeningProof[sw_bls12377.ScalarField, sw_bls12377.G1Affine](fr_bls12377.One(), tProof.ZShiftedOpening)
if err != nil {
return ret, fmt.Errorf("z shifted opening proof value assignment: %w", err)
}
Expand All @@ -88,27 +88,27 @@ func ValueOfProof[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2Ele
return ret, nil
}

func PlaceholderProof[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2ElementT](ccs constraint.ConstraintSystem) Proof[S, G1El, G2El] {
return Proof[S, G1El, G2El]{
BatchedProof: kzg.BatchOpeningProof[S, G1El]{
ClaimedValues: make([]S, 7),
Points: []S{},
func PlaceholderProof[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT](ccs constraint.ConstraintSystem) Proof[FR, G1El, G2El] {
return Proof[FR, G1El, G2El]{
BatchedProof: kzg.BatchOpeningProof[FR, G1El]{
ClaimedValues: make([]emulated.Element[FR], 7),
Points: []emulated.Element[FR]{},
},
}
}

type VerifyingKey[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2ElementT] struct {
type VerifyingKey[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT] struct {
// Size circuit
Size S
SizeInv S
Generator S
Size emulated.Element[FR]
SizeInv emulated.Element[FR]
Generator emulated.Element[FR]
NbPublicVariables uint64

// Commitment scheme that is used for an instantiation of PLONK
Kzg kzg.VerifyingKey[G2El]

// cosetShift generator of the coset on the small domain
CosetShift S
CosetShift emulated.Element[FR]

// S commitments to S1, S2, S3
S [3]kzg.Commitment[G1El]
Expand All @@ -122,16 +122,16 @@ type VerifyingKey[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2Ele
CommitmentConstraintIndexes []uint64
}

func ValueOfVerifyingKey[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2ElementT](vk backend_plonk.VerifyingKey) (VerifyingKey[S, G1El, G2El], error) {
var ret VerifyingKey[S, G1El, G2El]
func ValueOfVerifyingKey[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT](vk backend_plonk.VerifyingKey) (VerifyingKey[FR, G1El, G2El], error) {
var ret VerifyingKey[FR, G1El, G2El]
var err error
switch r := any(&ret).(type) {
case *VerifyingKey[sw_bls12377.Scalar, sw_bls12377.G1Affine, sw_bls12377.G2Affine]:
case *VerifyingKey[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine]:
tVk, ok := vk.(*plonkbackend_bls12377.VerifyingKey)
if !ok {
return ret, fmt.Errorf("expected bls12377.VerifyingKey, got %T", vk)
}
r.Size = tVk.Size
r.Size = emulated.ValueOf[sw_bls12377.ScalarField](tVk.Size)
r.SizeInv = sw_bls12377.NewScalar(tVk.SizeInv)
r.Generator = sw_bls12377.NewScalar(tVk.Generator)
r.NbPublicVariables = tVk.NbPublicVariables
Expand Down Expand Up @@ -181,105 +181,105 @@ func ValueOfVerifyingKey[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebr
return ret, nil
}

func PlaceholderVerifyingKey[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2ElementT](ccs constraint.ConstraintSystem) VerifyingKey[S, G1El, G2El] {
func PlaceholderVerifyingKey[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT](ccs constraint.ConstraintSystem) VerifyingKey[FR, G1El, G2El] {
// TODO: we're not considering the commitments right now
var ret VerifyingKey[S, G1El, G2El]
var ret VerifyingKey[FR, G1El, G2El]
return ret
}

// Witness is a public witness to verify the SNARK proof against. For assigning
// witness use [ValueOfWitness] and to create stub witness for compiling use
// [PlaceholderWitness].
type Witness[S algebra.ScalarT] struct {
type Witness[FR emulated.FieldParams] struct {
// Public is the public inputs. The first element does not need to be one
// wire and is added implicitly during verification.
Public []S
Public []emulated.Element[FR]
}

func ValueOfWitness[S algebra.ScalarT, G1 algebra.G1ElementT](w witness.Witness) (Witness[S], error) {
type dbwtiness[S algebra.ScalarT, G1 algebra.G1ElementT] struct {
W Witness[S]
}
var ret dbwtiness[S, G1]
func ValueOfWitness[FR emulated.FieldParams](w witness.Witness) (Witness[FR], error) {
var ret Witness[FR]
pubw, err := w.Public()
if err != nil {
return ret.W, fmt.Errorf("get public witness: %w", err)
return ret, fmt.Errorf("get public witness: %w", err)
}
vec := pubw.Vector()
switch s := any(&ret).(type) {
case *dbwtiness[emulated.Element[emparams.BN254Fr], sw_bn254.G1Affine]:
case *Witness[sw_bn254.ScalarField]:
vect, ok := vec.(fr_bn254.Vector)
if !ok {
return ret.W, fmt.Errorf("expected fr_bn254.Vector, got %T", vec)
return ret, fmt.Errorf("expected fr_bn254.Vector, got %T", vec)
}
for i := range vect {
s.W.Public = append(s.W.Public, emulated.ValueOf[emparams.BN254Fr](vect[i]))
s.Public = append(s.Public, sw_bn254.NewScalar(vect[i]))
}
case *dbwtiness[sw_bls12377.Scalar, sw_bls12377.G1Affine]:
case *Witness[sw_bls12377.ScalarField]:
vect, ok := vec.(fr_bls12377.Vector)
if !ok {
return ret.W, fmt.Errorf("expected fr_bls12377.Vector, got %T", vec)
return ret, fmt.Errorf("expected fr_bls12377.Vector, got %T", vec)
}
for i := range vect {
s.W.Public = append(s.W.Public, vect[i].String())
s.Public = append(s.Public, sw_bls12377.NewScalar(vect[i]))
}
case *dbwtiness[emulated.Element[emparams.BLS12381Fr], sw_bls12381.G1Affine]:
case *Witness[sw_bls12381.ScalarField]:
vect, ok := vec.(fr_bls12381.Vector)
if !ok {
return ret.W, fmt.Errorf("expected fr_bls12381.Vector, got %T", vec)
return ret, fmt.Errorf("expected fr_bls12381.Vector, got %T", vec)
}
for i := range vect {
s.W.Public = append(s.W.Public, emulated.ValueOf[emparams.BLS12381Fr](vect[i]))
s.Public = append(s.Public, sw_bls12381.NewScalar(vect[i]))
}
case *dbwtiness[sw_bls24315.Scalar, sw_bls24315.G1Affine]:
case *Witness[sw_bls24315.ScalarField]:
vect, ok := vec.(fr_bls24315.Vector)
if !ok {
return ret.W, fmt.Errorf("expected fr_bls24315.Vector, got %T", vec)
return ret, fmt.Errorf("expected fr_bls24315.Vector, got %T", vec)
}
for i := range vect {
s.W.Public = append(s.W.Public, vect[i].String())
s.Public = append(s.Public, sw_bls24315.NewScalar(vect[i]))
}
default:
return ret.W, fmt.Errorf("unknown parametric type combination")
return ret, fmt.Errorf("unknown parametric type combination")
}
return ret.W, nil
return ret, nil
}

// PlaceholderWitness creates a stub witness which can be used to allocate the
// variables in the circuit if the actual witness is not yet known. It takes
// into account the number of public inputs and number of used commitments.
func PlaceholderWitness[S algebra.ScalarT](ccs constraint.ConstraintSystem) Witness[S] {
return Witness[S]{
Public: make([]S, ccs.GetNbPublicVariables()),
func PlaceholderWitness[FR emulated.FieldParams](ccs constraint.ConstraintSystem) Witness[FR] {
return Witness[FR]{
Public: make([]emulated.Element[FR], ccs.GetNbPublicVariables()),
}
}

type Verifier[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2ElementT, GtEl algebra.GtElementT] struct {
type Verifier[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT, GtEl algebra.GtElementT] struct {
api frontend.API
curve algebra.Curve[S, G1El]
curve algebra.Curve[FR, G1El]
pairing algebra.Pairing[G1El, G2El, GtEl]
kzgHash hash.FieldHasher
fsHash hash.FieldHasher
htfHash hash.FieldHasher
}

func NewVerifier[
S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2ElementT, GtEl algebra.GtElementT](
api frontend.API, curve algebra.Curve[S, G1El], pairing algebra.Pairing[G1El, G2El, GtEl],
fsHash hash.FieldHasher) *Verifier[S, G1El, G2El, GtEl] {
return &Verifier[S, G1El, G2El, GtEl]{
FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT, GtEl algebra.GtElementT](
api frontend.API, curve algebra.Curve[FR, G1El], pairing algebra.Pairing[G1El, G2El, GtEl],
fsHash hash.FieldHasher) *Verifier[FR, G1El, G2El, GtEl] {
return &Verifier[FR, G1El, G2El, GtEl]{
api: api,
curve: curve,
pairing: pairing,
fsHash: fsHash,
}
}

func (v *Verifier[S, G1El, G2El, GtEl]) AssertProof(vk VerifyingKey[S, G1El, G2El], proof Proof[S, G1El, G2El], witness Witness[S]) error {
func (v *Verifier[FR, G1El, G2El, GtEl]) AssertProof(vk VerifyingKey[FR, G1El, G2El], proof Proof[FR, G1El, G2El], witness Witness[FR]) error {
if len(proof.Bsb22Commitments) != len(vk.Qcp) {
return fmt.Errorf("BSB22 commitment number mismatch")
}
fs := fiatshamir.NewTranscript(v.api, v.fsHash, []string{"gamma", "beta", "alpha", "zeta"})
fs, err := recursion.NewTranscript(v.api, nil, []string{"gamma", "beta", "alpha", "zeta"})
if err != nil {
return fmt.Errorf("init new transcript: %w", err)
}

if err := v.bindPublicData(fs, "gamma", vk, witness); err != nil {
return fmt.Errorf("bind public data: %w", err)
Expand Down Expand Up @@ -519,7 +519,7 @@ func (v *Verifier[S, G1El, G2El, GtEl]) AssertProof(vk VerifyingKey[S, G1El, G2E
return nil
}

func (v *Verifier[S, G1El, G2El, GtEl]) bindPublicData(fs *fiatshamir.Transcript, challenge string, vk VerifyingKey[S, G1El, G2El], witness Witness[S]) error {
func (v *Verifier[FR, G1El, G2El, GtEl]) bindPublicData(fs *fiatshamir.Transcript, challenge string, vk VerifyingKey[FR, G1El, G2El], witness Witness[FR]) error {
// permutation
if err := fs.Bind(challenge, v.curve.MarshalG1(vk.S[0].G1El)); err != nil {
return err
Expand Down Expand Up @@ -563,8 +563,8 @@ func (v *Verifier[S, G1El, G2El, GtEl]) bindPublicData(fs *fiatshamir.Transcript
return nil
}

func (v *Verifier[S, G1El, G2El, GtEl]) deriveRandomness(fs *fiatshamir.Transcript, challenge string, points ...G1El) (S, error) {
var ret S
func (v *Verifier[FR, G1El, G2El, GtEl]) deriveRandomness(fs *fiatshamir.Transcript, challenge string, points ...G1El) (emulated.Element[FR], error) {
var ret emulated.Element[FR]
for i := range points {
if err := fs.Bind(challenge, v.curve.MarshalG1(points[i])); err != nil {
return ret, fmt.Errorf("bind challenge %d: %w", i, err)
Expand Down
25 changes: 13 additions & 12 deletions std/recursion/plonk/verifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/consensys/gnark/frontend/cs/scs"
"github.com/consensys/gnark/std/algebra"
"github.com/consensys/gnark/std/algebra/native/sw_bls12377"
"github.com/consensys/gnark/std/math/emulated"
"github.com/consensys/gnark/std/recursion"
"github.com/consensys/gnark/test"
)
Expand Down Expand Up @@ -58,10 +59,10 @@ func getInner(assert *test.Assert, field, outer *big.Int) (constraint.Constraint
return innerCcs, innerVK, innerPubWitness, innerProof
}

type OuterCircuit[S algebra.ScalarT, G1El algebra.G1ElementT, G2El algebra.G2ElementT, GtEl algebra.GtElementT] struct {
Proof Proof[S, G1El, G2El]
VerifyingKey VerifyingKey[S, G1El, G2El]
InnerWitness Witness[S]
type OuterCircuit[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT, GtEl algebra.GtElementT] struct {
Proof Proof[FR, G1El, G2El]
VerifyingKey VerifyingKey[FR, G1El, G2El]
InnerWitness Witness[FR]

target *big.Int // TODO: remove later
}
Expand Down Expand Up @@ -90,20 +91,20 @@ func TestBLS12InBW6(t *testing.T) {
innerCcs, innerVK, innerWitness, innerProof := getInner(assert, ecc.BLS12_377.ScalarField(), ecc.BW6_761.ScalarField())

// outer proof
circuitVk, err := ValueOfVerifyingKey[sw_bls12377.Scalar, sw_bls12377.G1Affine, sw_bls12377.G2Affine](innerVK)
circuitVk, err := ValueOfVerifyingKey[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](innerVK)
assert.NoError(err)
circuitWitness, err := ValueOfWitness[sw_bls12377.Scalar, sw_bls12377.G1Affine](innerWitness)
circuitWitness, err := ValueOfWitness[sw_bls12377.ScalarField](innerWitness)
assert.NoError(err)
circuitProof, err := ValueOfProof[sw_bls12377.Scalar, sw_bls12377.G1Affine, sw_bls12377.G2Affine](innerProof)
circuitProof, err := ValueOfProof[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](innerProof)
assert.NoError(err)

outerCircuit := &OuterCircuit[sw_bls12377.Scalar, sw_bls12377.G1Affine, sw_bls12377.G2Affine, sw_bls12377.GT]{
InnerWitness: PlaceholderWitness[sw_bls12377.Scalar](innerCcs),
Proof: PlaceholderProof[sw_bls12377.Scalar, sw_bls12377.G1Affine, sw_bls12377.G2Affine](innerCcs),
VerifyingKey: PlaceholderVerifyingKey[sw_bls12377.Scalar, sw_bls12377.G1Affine, sw_bls12377.G2Affine](innerCcs),
outerCircuit := &OuterCircuit[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine, sw_bls12377.GT]{
InnerWitness: PlaceholderWitness[sw_bls12377.ScalarField](innerCcs),
Proof: PlaceholderProof[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](innerCcs),
VerifyingKey: PlaceholderVerifyingKey[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](innerCcs),
target: ecc.BLS12_377.ScalarField(),
}
outerAssignment := &OuterCircuit[sw_bls12377.Scalar, sw_bls12377.G1Affine, sw_bls12377.G2Affine, sw_bls12377.GT]{
outerAssignment := &OuterCircuit[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine, sw_bls12377.GT]{
InnerWitness: circuitWitness,
Proof: circuitProof,
VerifyingKey: circuitVk,
Expand Down

0 comments on commit 2116255

Please sign in to comment.