Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
mattstam committed Feb 8, 2024
1 parent 700e9da commit 8df0aca
Show file tree
Hide file tree
Showing 4 changed files with 274 additions and 551 deletions.
202 changes: 202 additions & 0 deletions plonky2x/verifier/system/groth16_deserializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,213 @@ import (
"io"

"github.com/consensys/gnark-crypto/ecc/bn254/fp"
"github.com/consensys/gnark-crypto/ecc/bn254/fr"
"github.com/consensys/gnark-crypto/ecc/bn254/fr/iop"

"github.com/consensys/gnark-crypto/ecc/bn254"
"github.com/consensys/gnark/backend/groth16"
groth16Bn254 "github.com/consensys/gnark/backend/groth16/bn254"
)

// func readV08ProvingKey(pk *groth16Bn254.ProvingKey, r io.Reader) (int64, error) {
// dec := bn254.NewDecoder(r)

// // Read domain
// if err := dec.Decode(&pk.Domain); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.Domain", pk.Domain)
// // Read G1 (Alpha, Beta, Delta, A, B, Z, K)
// if err := dec.Decode(&pk.G1.Alpha); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.G1.Alpha", pk.G1.Alpha)
// if err := dec.Decode(&pk.G1.Beta); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.G1.Beta", pk.G1.Beta)
// if err := dec.Decode(&pk.G1.Delta); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.G1.Delta", pk.G1.Delta)
// if err := dec.Decode(&pk.G1.A); err != nil {
// return dec.BytesRead(), err
// }
// if err := dec.Decode(&pk.G1.B); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.G1.B", pk.G1.B)
// if err := dec.Decode(&pk.G1.Z); err != nil {
// return dec.BytesRead(), err
// }
// if err := dec.Decode(&pk.G1.K); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.G1.K", pk.G1.K)

// // Read G2 (Beta, Delta, B)
// if err := dec.Decode(&pk.G2.Beta); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.G2.Beta", pk.G2.Beta)
// if err := dec.Decode(&pk.G2.Delta); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.G2.Delta", pk.G2.Delta)
// if err := dec.Decode(&pk.G2.B); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.G2.B", pk.G2.B)

// // Read InfinityA, InfinityB, NbInfinityA, NbInfinityB
// if err := dec.Decode(&pk.InfinityA); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.InfinityA", pk.InfinityA)
// if err := dec.Decode(&pk.InfinityB); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.InfinityB", pk.InfinityB)
// if err := dec.Decode(&pk.NbInfinityA); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.NbInfinityA", pk.NbInfinityA)
// if err := dec.Decode(&pk.NbInfinityB); err != nil {
// return dec.BytesRead(), err
// }
// fmt.Println("pk.NbInfinityB", pk.NbInfinityB)

// return dec.BytesRead(), nil
// }

func readV08ProvingKey(pk *groth16Bn254.ProvingKey, r io.Reader) (int64, error) {
pk.Vk = &groth16.VerifyingKey{}
n, err := pk.Vk.ReadFrom(r)
if err != nil {
return n, err
}

n2, err, chDomain0 := pk.Domain[0].AsyncReadFrom(r)
n += n2
if err != nil {
return n, err
}

n2, err, chDomain1 := pk.Domain[1].AsyncReadFrom(r)
n += n2
if err != nil {
return n, err
}

if withSubgroupChecks {
n2, err = pk.Kzg.ReadFrom(r)
} else {
n2, err = pk.Kzg.UnsafeReadFrom(r)
}
n += n2
if err != nil {
return n, err
}
if withSubgroupChecks {
n2, err = pk.KzgLagrange.ReadFrom(r)
} else {
n2, err = pk.KzgLagrange.UnsafeReadFrom(r)
}
n += n2
if err != nil {
return n, err
}

pk.trace.S = make([]int64, 3*pk.Domain[0].Cardinality)

dec := curve.NewDecoder(r)

var ql, qr, qm, qo, qk, s1, s2, s3 []fr.Element
var qcp [][]fr.Element

// TODO @gbotrel: this is a bit ugly, we should probably refactor this.
// The order of the variables is important, as it matches the order in which they are
// encoded in the WriteTo(...) method.

// Note: instead of calling dec.Decode(...) for each of the above variables,
// we call AsyncReadFrom when possible which allows to consume bytes from the reader
// and perform the decoding in parallel

type v struct {
data *fr.Vector
chErr chan error
}

vectors := make([]v, 8)
vectors[0] = v{data: (*fr.Vector)(&ql)}
vectors[1] = v{data: (*fr.Vector)(&qr)}
vectors[2] = v{data: (*fr.Vector)(&qm)}
vectors[3] = v{data: (*fr.Vector)(&qo)}
vectors[4] = v{data: (*fr.Vector)(&qk)}
vectors[5] = v{data: (*fr.Vector)(&s1)}
vectors[6] = v{data: (*fr.Vector)(&s2)}
vectors[7] = v{data: (*fr.Vector)(&s3)}

// read ql, qr, qm, qo, qk
for i := 0; i < 5; i++ {
n2, err, ch := vectors[i].data.AsyncReadFrom(r)
n += n2
if err != nil {
return n, err
}
vectors[i].chErr = ch
}

// read qcp
if err := dec.Decode(&qcp); err != nil {
return n + dec.BytesRead(), err
}

// read lqk, s1, s2, s3
for i := 5; i < 8; i++ {
n2, err, ch := vectors[i].data.AsyncReadFrom(r)
n += n2
if err != nil {
return n, err
}
vectors[i].chErr = ch
}

// read pk.Trace.S
if err := dec.Decode(&pk.trace.S); err != nil {
return n + dec.BytesRead(), err
}

// wait for all AsyncReadFrom(...) to complete
for i := range vectors {
if err := <-vectors[i].chErr; err != nil {
return n, err
}
}

canReg := iop.Form{Basis: iop.Canonical, Layout: iop.Regular}
pk.trace.Ql = iop.NewPolynomial(&ql, canReg)
pk.trace.Qr = iop.NewPolynomial(&qr, canReg)
pk.trace.Qm = iop.NewPolynomial(&qm, canReg)
pk.trace.Qo = iop.NewPolynomial(&qo, canReg)
pk.trace.Qk = iop.NewPolynomial(&qk, canReg)
pk.trace.S1 = iop.NewPolynomial(&s1, canReg)
pk.trace.S2 = iop.NewPolynomial(&s2, canReg)
pk.trace.S3 = iop.NewPolynomial(&s3, canReg)

pk.trace.Qcp = make([]*iop.Polynomial, len(qcp))
for i := range qcp {
pk.trace.Qcp[i] = iop.NewPolynomial(&qcp[i], canReg)
}

// wait for FFT to be precomputed
<-chDomain0
<-chDomain1

return n + dec.BytesRead(), nil

}

func readV08VerifyingKey(vk *groth16Bn254.VerifyingKey, r io.Reader) (int64, error) {
dec := bn254.NewDecoder(r)
if err := dec.Decode(&vk.G1.Alpha); err != nil {
Expand Down
10 changes: 5 additions & 5 deletions plonky2x/verifier/system/plonk.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/consensys/gnark/backend/witness"
"github.com/consensys/gnark/constraint"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/frontend/cs/r1cs"
"github.com/consensys/gnark/frontend/cs/scs"
"github.com/consensys/gnark/test"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
Expand Down Expand Up @@ -158,25 +158,25 @@ func (s *PlonkSystem) CompileVerifierCircuit() (constraint.ConstraintSystem, plo
OutputHash: new(frontend.Variable),
CommonCircuitData: commonCircuitData,
}
r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
scs, err := frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, &circuit)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "compile verifier circuit")
}

s.logger.Info("Running circuit setup")
start := time.Now()
srs, err := test.NewKZGSRS(r1cs)
srs, err := test.NewKZGSRS(scs)
if err != nil {
panic(err)
}
pk, vk, err := plonk.Setup(r1cs, srs)
pk, vk, err := plonk.Setup(scs, srs)
if err != nil {
return nil, nil, nil, err
}
elapsed := time.Since(start)
s.logger.Info("Successfully ran circuit setup", zap.String("time", elapsed.String()))

return r1cs, pk, vk, nil
return scs, pk, vk, nil
}

func (s *PlonkSystem) SaveVerifierCircuit(r1cs constraint.ConstraintSystem, pk plonk.ProvingKey, vk plonk.VerifyingKey) error {
Expand Down
67 changes: 67 additions & 0 deletions plonky2x/verifier/system/x.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// ReadFrom attempts to decode a VerifyingKey from reader
// VerifyingKey must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed)
// serialization format:
// https://github.com/zkcrypto/bellman/blob/fa9be45588227a8c6ec34957de3f68705f07bd92/src/groth16/mod.rs#L143
// [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2,uint32(len(Kvk)),[Kvk]1
func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) {
n, err := vk.readFrom(r)
if err != nil {
return n, err
}
var m int64
m, err = vk.CommitmentKey.ReadFrom(r)
return m + n, err
}

// UnsafeReadFrom has the same behavior as ReadFrom, except that it will not check that decode points
// are on the curve and in the correct subgroup.
func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) {
n, err := vk.readFrom(r, curve.NoSubgroupChecks())
if err != nil {
return n, err
}
var m int64
m, err = vk.CommitmentKey.UnsafeReadFrom(r)
return m + n, err
}

func (vk *VerifyingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) {
dec := curve.NewDecoder(r, decOptions...)

// [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2
if err := dec.Decode(&vk.G1.Alpha); err != nil {
return dec.BytesRead(), err
}
if err := dec.Decode(&vk.G1.Beta); err != nil {
return dec.BytesRead(), err
}
if err := dec.Decode(&vk.G2.Beta); err != nil {
return dec.BytesRead(), err
}
if err := dec.Decode(&vk.G2.Gamma); err != nil {
return dec.BytesRead(), err
}
if err := dec.Decode(&vk.G1.Delta); err != nil {
return dec.BytesRead(), err
}
if err := dec.Decode(&vk.G2.Delta); err != nil {
return dec.BytesRead(), err
}

// uint32(len(Kvk)),[Kvk]1
if err := dec.Decode(&vk.G1.K); err != nil {
return dec.BytesRead(), err
}
var publicCommitted [][]uint64
if err := dec.Decode(&publicCommitted); err != nil {
return dec.BytesRead(), err
}
vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted)

// recompute vk.e (e(α, β)) and -[δ]2, -[γ]2
if err := vk.Precompute(); err != nil {
return dec.BytesRead(), err
}

return dec.BytesRead(), nil
}
Loading

0 comments on commit 8df0aca

Please sign in to comment.