https://github.com/yacovm/ZKAT-VDP
Tip revision: 721f52b1b74f8e0aa60799bd1436865f8020258e authored by yacovm on 14 August 2023, 13:43:45 UTC
Create README.md
Create README.md
Tip revision: 721f52b
deltacircuit.go
package deltacircuit
import (
//"crypto/subtle"
tedwards "github.com/consensys/gnark-crypto/ecc/twistededwards"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/algebra/twistededwards"
"github.com/consensys/gnark/std/math/bits"
eddsa "github.com/consensys/gnark/std/signature/eddsa"
"github.com/consensys/gnark/std/hash/mimc"
)
type Point struct {
X, Y frontend.Variable
}
type deltaCircuit struct {
// Random value agreed upon with the census
Coin0 frontend.Variable
Coin1 frontend.Variable
Xi frontend.Variable
CMXi frontend.Variable `gnark:",public"`
// private value hidden by LDP
ID frontend.Variable
LDPVal frontend.Variable
Delta Point `gnark:",public"` // Delta = Encrypt(LDP(ID,Xi))
curveID tedwards.ID
// Variables used for the elgamal encryption
RNDscalar frontend.Variable
CensusPK eddsa.PublicKey `gnark:",public"` // Public key of the census
ApkList []frontend.Variable
RegAuthorityPK eddsa.PublicKey `gnark:",public"`
RegAuthoritySignature eddsa.Signature
}
// Define declares the circuit logic. The compiler then produces a list of constraints
// which must be satisfied (valid witness) in order to create a valid zk-SNARK
func (circuit *deltaCircuit) Define(api frontend.API) error {
// Create the encryption circuit
curve, err := twistededwards.NewEdCurve(api, circuit.curveID)
if err != nil {
return err
}
hfunc, err := mimc.NewMiMC(api)
if err != nil {
return err
}
hfunc.Write(circuit.Xi)
result := hfunc.Sum()
api.AssertIsEqual(result, circuit.CMXi)
ldpval, _ := LDP(api, circuit.Coin0, circuit.Coin1, circuit.Xi, circuit.ID)
api.AssertIsEqual(ldpval, circuit.LDPVal)
err = Encrypt(curve, circuit.RNDscalar, circuit.CensusPK, ldpval, circuit.Delta)
if err != nil {
return err
}
hfunc.Reset()
hfunc.Write(circuit.ApkList[:]...)
hfunc.Write(circuit.ID)
signdata := hfunc.Sum()
// Verify sign_R
mimcSign, err := mimc.NewMiMC(api)
if err != nil {
return err
}
err = eddsa.Verify(curve, circuit.RegAuthoritySignature, signdata, circuit.RegAuthorityPK, &mimcSign)
if err != nil {
return err
}
return nil
}
func LDP(api frontend.API, coin0, coin1, xi, msg frontend.Variable) (frontend.Variable, error) {
coins := bits.ToBinary(api, xi)
api.AssertIsEqual(coins[0], coin0)
api.AssertIsEqual(coins[1], coin1)
// Create the LDP circuit
c0 := api.IsZero(coins[0]) // Check first coin toss
c1 := api.IsZero(coins[1]) // Check second coin toss
ldp := api.Select(c0, msg, c1) // Calculate Random Response result
return ldp, nil
}
// Encrypt creates the circuit matching the elgamal encryption
func Encrypt(curve twistededwards.Curve, r frontend.Variable, pubkey eddsa.PublicKey, msg frontend.Variable, delta Point) error {
base := twistededwards.Point{
X: curve.Params().Base[0],
Y: curve.Params().Base[1],
}
// project the message on to the curve
M := curve.ScalarMul(base, msg)
curve.AssertIsOnCurve(M)
// ElGamal-encrypt the point to produce ciphertext (K,C).
//K := curve.ScalarMul(base, r) // K = r * Base - Public key
S := curve.ScalarMul(pubkey.A, r) // S = r*A
curve.AssertIsOnCurve(S)
Cipher := curve.Add(S, M) // C = S + M
curve.API().AssertIsEqual(Cipher.X, delta.X)
curve.API().AssertIsEqual(Cipher.Y, delta.Y)
return nil
}
