@ -1,11 +1,12 @@
package snark
package snark
import (
import (
"crypto/rand"
"fmt"
"fmt"
"math/big"
"math/big"
"os"
"github.com/arnaucube/go-snark/bn128"
"github.com/arnaucube/go-snark/bn128"
"github.com/arnaucube/go-snark/compiler"
"github.com/arnaucube/go-snark/fields"
"github.com/arnaucube/go-snark/fields"
"github.com/arnaucube/go-snark/r1csqap"
"github.com/arnaucube/go-snark/r1csqap"
)
)
@ -36,9 +37,10 @@ type Setup struct {
Cp [ ] [ 3 ] * big . Int
Cp [ ] [ 3 ] * big . Int
}
}
Vk struct {
Vk struct {
A [ 3 ] [ 2 ] * big . Int
B [ 3 ] * big . Int
C [ 3 ] [ 2 ] * big . Int
Vka [ 3 ] [ 2 ] * big . Int
Vkb [ 3 ] * big . Int
Vkc [ 3 ] [ 2 ] * big . Int
A [ ] [ 3 ] * big . Int
G1Kbg [ 3 ] * big . Int // g1 * Kbeta * Kgamma
G1Kbg [ 3 ] * big . Int // g1 * Kbeta * Kgamma
G2Kbg [ 3 ] [ 2 ] * big . Int // g2 * Kbeta * Kgamma
G2Kbg [ 3 ] [ 2 ] * big . Int // g2 * Kbeta * Kgamma
G2Kg [ 3 ] [ 2 ] * big . Int // g2 * Kgamma
G2Kg [ 3 ] [ 2 ] * big . Int // g2 * Kgamma
@ -47,67 +49,66 @@ type Setup struct {
}
}
type Proof struct {
type Proof struct {
PiA [ 3 ] * big . Int
PiAp [ 3 ] * big . Int
PiB [ 3 ] [ 2 ] * big . Int
PiBp [ 3 ] * big . Int
PiC [ 3 ] * big . Int
PiCp [ 3 ] * big . Int
PiH [ 3 ] * big . Int
PiKp [ 3 ] * big . Int
PiA [ 3 ] * big . Int
PiAp [ 3 ] * big . Int
PiB [ 3 ] [ 2 ] * big . Int
PiBp [ 3 ] * big . Int
PiC [ 3 ] * big . Int
PiCp [ 3 ] * big . Int
PiH [ 3 ] * big . Int
PiKp [ 3 ] * big . Int
PublicSignals [ ] * big . Int
}
}
const bits = 512
func GenerateTrustedSetup ( bn bn128 . Bn128 , pf r1csqap . PolynomialField , witnessLength int , alphas , betas , gammas [ ] [ ] * big . Int , ax , bx , cx , hx , zx [ ] * big . Int ) ( Setup , error ) {
func GenerateTrustedSetup ( bn bn128 . Bn128 , fqR fields . Fq , pf r1csqap . PolynomialField , witnessLength int , circuit compiler . Circuit , alphas , betas , gammas [ ] [ ] * big . Int , zx [ ] * big . Int ) ( Setup , error ) {
var setup Setup
var setup Setup
var err error
var err error
// generate random t value
// generate random t value
setup . Toxic . T , err = rand . Prime ( rand . Reader , bits )
setup . Toxic . T , err = fqR . Rand ( )
if err != nil {
if err != nil {
return Setup { } , err
return Setup { } , err
}
}
// k for calculating pi' and Vk
// k for calculating pi' and Vk
setup . Toxic . Ka , err = rand . Prime ( rand . Reader , bits )
setup . Toxic . Ka , err = fqR . Rand ( )
if err != nil {
if err != nil {
return Setup { } , err
return Setup { } , err
}
}
setup . Toxic . Kb , err = rand . Prime ( rand . Reader , bits )
setup . Toxic . Kb , err = fqR . Rand ( )
if err != nil {
if err != nil {
return Setup { } , err
return Setup { } , err
}
}
setup . Toxic . Kc , err = rand . Prime ( rand . Reader , bits )
setup . Toxic . Kc , err = fqR . Rand ( )
if err != nil {
if err != nil {
return Setup { } , err
return Setup { } , err
}
}
// generate Kβ (Kbeta) and Kγ (Kgamma)
// generate Kβ (Kbeta) and Kγ (Kgamma)
setup . Toxic . Kbeta , err = rand . Prime ( rand . Reader , bits )
setup . Toxic . Kbeta , err = fqR . Rand ( )
if err != nil {
if err != nil {
return Setup { } , err
return Setup { } , err
}
}
setup . Toxic . Kgamma , err = rand . Prime ( rand . Reader , bits )
setup . Toxic . Kgamma , err = fqR . Rand ( )
if err != nil {
if err != nil {
return Setup { } , err
return Setup { } , err
}
}
// generate ρ (Rho): ρA, ρB, ρC
// generate ρ (Rho): ρA, ρB, ρC
setup . Toxic . RhoA , err = rand . Prime ( rand . Reader , bits )
setup . Toxic . RhoA , err = fqR . Rand ( )
if err != nil {
if err != nil {
return Setup { } , err
return Setup { } , err
}
}
setup . Toxic . RhoB , err = rand . Prime ( rand . Reader , bits )
setup . Toxic . RhoB , err = fqR . Rand ( )
if err != nil {
if err != nil {
return Setup { } , err
return Setup { } , err
}
}
setup . Toxic . RhoC = bn . Fq1 . Mul ( setup . Toxic . RhoA , setup . Toxic . RhoB )
setup . Toxic . RhoC = fqR . Mul ( setup . Toxic . RhoA , setup . Toxic . RhoB )
// encrypt t values with curve generators
// encrypt t values with curve generators
var gt1 [ ] [ 3 ] * big . Int
var gt1 [ ] [ 3 ] * big . Int
var gt2 [ ] [ 3 ] [ 2 ] * big . Int
var gt2 [ ] [ 3 ] [ 2 ] * big . Int
for i := 0 ; i < witnessLength ; i ++ {
for i := 0 ; i < witnessLength ; i ++ {
tPow := bn . Fq1 . Exp ( setup . Toxic . T , big . NewInt ( int64 ( i ) ) )
tPow := fqR . Exp ( setup . Toxic . T , big . NewInt ( int64 ( i ) ) )
tEncr1 := bn . G1 . MulScalar ( bn . G1 . G , tPow )
tEncr1 := bn . G1 . MulScalar ( bn . G1 . G , tPow )
gt1 = append ( gt1 , tEncr1 )
gt1 = append ( gt1 , tEncr1 )
tEncr2 := bn . G2 . MulScalar ( bn . G2 . G , tPow )
tEncr2 := bn . G2 . MulScalar ( bn . G2 . G , tPow )
@ -118,9 +119,9 @@ func GenerateTrustedSetup(bn bn128.Bn128, pf r1csqap.PolynomialField, witnessLen
setup . G1T = gt1
setup . G1T = gt1
setup . G2T = gt2
setup . G2T = gt2
setup . Vk . A = bn . G2 . MulScalar ( bn . G2 . G , setup . Toxic . Ka )
setup . Vk . B = bn . G1 . MulScalar ( bn . G1 . G , setup . Toxic . Kb )
setup . Vk . C = bn . G2 . MulScalar ( bn . G2 . G , setup . Toxic . Kc )
setup . Vk . Vka = bn . G2 . MulScalar ( bn . G2 . G , setup . Toxic . Ka )
setup . Vk . Vkb = bn . G1 . MulScalar ( bn . G1 . G , setup . Toxic . Kb )
setup . Vk . Vkc = bn . G2 . MulScalar ( bn . G2 . G , setup . Toxic . Kc )
/ *
/ *
Verification keys :
Verification keys :
@ -128,16 +129,19 @@ func GenerateTrustedSetup(bn bn128.Bn128, pf r1csqap.PolynomialField, witnessLen
- Vk_betagamma2 : setup . G2Kbg = g2 * Kbeta * Kgamma
- Vk_betagamma2 : setup . G2Kbg = g2 * Kbeta * Kgamma
- Vk_gamma : setup . G2Kg = g2 * Kgamma
- Vk_gamma : setup . G2Kg = g2 * Kgamma
* /
* /
kbg := bn . Fq1 . Mul ( setup . Toxic . Kbeta , setup . Toxic . Kgamma )
kbg := fqR . Mul ( setup . Toxic . Kbeta , setup . Toxic . Kgamma )
setup . Vk . G1Kbg = bn . G1 . MulScalar ( bn . G1 . G , kbg )
setup . Vk . G1Kbg = bn . G1 . MulScalar ( bn . G1 . G , kbg )
setup . Vk . G2Kbg = bn . G2 . MulScalar ( bn . G2 . G , kbg )
setup . Vk . G2Kbg = bn . G2 . MulScalar ( bn . G2 . G , kbg )
setup . Vk . G2Kg = bn . G2 . MulScalar ( bn . G2 . G , setup . Toxic . Kgamma )
setup . Vk . G2Kg = bn . G2 . MulScalar ( bn . G2 . G , setup . Toxic . Kgamma )
for i := 0 ; i < witnessLength ; i ++ {
// A[i] = g1 * ax[t]
// for i := 0; i < circuit.NSignals; i++ {
for i := 0 ; i < circuit . NVars ; i ++ {
at := pf . Eval ( alphas [ i ] , setup . Toxic . T )
at := pf . Eval ( alphas [ i ] , setup . Toxic . T )
a := bn . G1 . MulScalar ( bn . G1 . G , at )
a := bn . G1 . MulScalar ( bn . G1 . G , at )
setup . Pk . A = append ( setup . Pk . A , a )
setup . Pk . A = append ( setup . Pk . A , a )
if i <= circuit . NPublic {
setup . Vk . A = append ( setup . Vk . A , a )
}
bt := pf . Eval ( betas [ i ] , setup . Toxic . T )
bt := pf . Eval ( betas [ i ] , setup . Toxic . T )
bg1 := bn . G1 . MulScalar ( bn . G1 . G , bt )
bg1 := bn . G1 . MulScalar ( bn . G1 . G , bt )
@ -148,20 +152,27 @@ func GenerateTrustedSetup(bn bn128.Bn128, pf r1csqap.PolynomialField, witnessLen
c := bn . G1 . MulScalar ( bn . G1 . G , ct )
c := bn . G1 . MulScalar ( bn . G1 . G , ct )
setup . Pk . C = append ( setup . Pk . C , c )
setup . Pk . C = append ( setup . Pk . C , c )
kt := bn . Fq1 . Add ( bn . Fq1 . Add ( at , bt ) , ct )
k := bn . G1 . MulScalar ( bn . G1 . G , kt )
kt := fqR . Add ( fqR . Add ( at , bt ) , ct )
k := bn . G1 . Affine ( bn . G1 . MulScalar ( bn . G1 . G , kt ) )
ktest := bn . G1 . Affine ( bn . G1 . Add ( bn . G1 . Add ( a , bg1 ) , c ) )
if ! bn . Fq2 . Equal ( k , ktest ) {
os . Exit ( 1 )
return setup , err
}
setup . Pk . Ap = append ( setup . Pk . Ap , bn . G1 . MulScalar ( a , setup . Toxic . Ka ) )
setup . Pk . Ap = append ( setup . Pk . Ap , bn . G1 . MulScalar ( a , setup . Toxic . Ka ) )
setup . Pk . Bp = append ( setup . Pk . Bp , bn . G1 . MulScalar ( bg1 , setup . Toxic . Kb ) )
setup . Pk . Bp = append ( setup . Pk . Bp , bn . G1 . MulScalar ( bg1 , setup . Toxic . Kb ) )
setup . Pk . Cp = append ( setup . Pk . Cp , bn . G1 . MulScalar ( c , setup . Toxic . Kc ) )
setup . Pk . Cp = append ( setup . Pk . Cp , bn . G1 . MulScalar ( c , setup . Toxic . Kc ) )
setup . Pk . Kp = append ( setup . Pk . Kp , bn . G1 . MulScalar ( k , setup . Toxic . Kbeta ) )
k_ := bn . G1 . MulScalar ( bn . G1 . G , kt )
setup . Pk . Kp = append ( setup . Pk . Kp , bn . G1 . MulScalar ( k_ , setup . Toxic . Kbeta ) )
}
}
setup . Vk . Vkz = bn . G2 . MulScalar ( bn . G2 . G , pf . Eval ( zx , setup . Toxic . T ) )
setup . Vk . Vkz = bn . G2 . MulScalar ( bn . G2 . G , pf . Eval ( zx , setup . Toxic . T ) )
return setup , nil
return setup , nil
}
}
func GenerateProofs ( bn bn128 . Bn128 , f fields . Fq , setup Setup , hx [ ] * big . Int , w [ ] * big . Int ) ( Proof , error ) {
func GenerateProofs ( bn bn128 . Bn128 , f fields . Fq , circuit compiler . Circuit , setup Setup , hx [ ] * big . Int , w [ ] * big . Int ) ( Proof , error ) {
var proof Proof
var proof Proof
proof . PiA = [ 3 ] * big . Int { bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) }
proof . PiA = [ 3 ] * big . Int { bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) }
proof . PiAp = [ 3 ] * big . Int { bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) }
proof . PiAp = [ 3 ] * big . Int { bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) }
@ -172,12 +183,12 @@ func GenerateProofs(bn bn128.Bn128, f fields.Fq, setup Setup, hx []*big.Int, w [
proof . PiH = [ 3 ] * big . Int { bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) }
proof . PiH = [ 3 ] * big . Int { bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) }
proof . PiKp = [ 3 ] * big . Int { bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) }
proof . PiKp = [ 3 ] * big . Int { bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) , bn . G1 . F . Zero ( ) }
for i := 0 ; i < len ( w ) ; i ++ {
for i := circuit . NPublic + 1 ; i < circuit . NVars ; i ++ {
proof . PiA = bn . G1 . Add ( proof . PiA , bn . G1 . MulScalar ( setup . Pk . A [ i ] , w [ i ] ) )
proof . PiA = bn . G1 . Add ( proof . PiA , bn . G1 . MulScalar ( setup . Pk . A [ i ] , w [ i ] ) )
proof . PiAp = bn . G1 . Add ( proof . PiAp , bn . G1 . MulScalar ( setup . Pk . Ap [ i ] , w [ i ] ) )
proof . PiAp = bn . G1 . Add ( proof . PiAp , bn . G1 . MulScalar ( setup . Pk . Ap [ i ] , w [ i ] ) )
}
}
for i := 0 ; i < len ( w ) ; i ++ {
for i := 0 ; i < circuit . NVars ; i ++ {
proof . PiB = bn . G2 . Add ( proof . PiB , bn . G2 . MulScalar ( setup . Pk . B [ i ] , w [ i ] ) )
proof . PiB = bn . G2 . Add ( proof . PiB , bn . G2 . MulScalar ( setup . Pk . B [ i ] , w [ i ] ) )
proof . PiBp = bn . G1 . Add ( proof . PiBp , bn . G1 . MulScalar ( setup . Pk . Bp [ i ] , w [ i ] ) )
proof . PiBp = bn . G1 . Add ( proof . PiBp , bn . G1 . MulScalar ( setup . Pk . Bp [ i ] , w [ i ] ) )
@ -186,122 +197,73 @@ func GenerateProofs(bn bn128.Bn128, f fields.Fq, setup Setup, hx []*big.Int, w [
proof . PiKp = bn . G1 . Add ( proof . PiKp , bn . G1 . MulScalar ( setup . Pk . Kp [ i ] , w [ i ] ) )
proof . PiKp = bn . G1 . Add ( proof . PiKp , bn . G1 . MulScalar ( setup . Pk . Kp [ i ] , w [ i ] ) )
}
}
for i := 0 ; i < len ( hx ) ; i ++ {
for i := 0 ; i < len ( hx ) ; i ++ {
proof . PiH = bn . G1 . Add ( proof . PiH , bn . G1 . MulScalar ( setup . G1T [ i ] , hx [ i ] ) )
proof . PiH = bn . G1 . Add ( proof . PiH , bn . G1 . MulScalar ( setup . G1T [ i ] , hx [ i ] ) )
}
}
proof . PublicSignals = w [ 1 : circuit . NPublic + 1 ]
return proof , nil
return proof , nil
}
}
func VerifyProof ( bn bn128 . Bn128 , setup Setup , proof Proof ) bool {
func VerifyProof ( bn bn128 . Bn128 , circuit compiler . Circuit , setup Setup , proof Proof ) bool {
// e(piA, Va) == e(piA', g2)
// e(piA, Va) == e(piA', g2)
pairingPiaVa , err := bn . Pairing ( proof . PiA , setup . Vk . A )
if err != nil {
return false
}
pairingPiapG2 , err := bn . Pairing ( proof . PiAp , bn . G2 . G )
if err != nil {
return false
}
pairingPiaVa := bn . Pairing ( proof . PiA , setup . Vk . Vka )
pairingPiapG2 := bn . Pairing ( proof . PiAp , bn . G2 . G )
if ! bn . Fq12 . Equal ( pairingPiaVa , pairingPiapG2 ) {
if ! bn . Fq12 . Equal ( pairingPiaVa , pairingPiapG2 ) {
return false
return false
} else {
} else {
fmt . Println ( "valid knowledge commitment for A" )
fmt . Println ( "✓ e(piA, Va) == e(piA', g2), valid knowledge commitment for A" )
}
}
// e(Vb, piB) == e(piB', g2)
// e(Vb, piB) == e(piB', g2)
pairingVbPib , err := bn . Pairing ( setup . Vk . B , proof . PiB )
if err != nil {
return false
}
pairingPibpG2 , err := bn . Pairing ( proof . PiBp , bn . G2 . G )
if err != nil {
return false
}
pairingVbPib := bn . Pairing ( setup . Vk . Vkb , proof . PiB )
pairingPibpG2 := bn . Pairing ( proof . PiBp , bn . G2 . G )
if ! bn . Fq12 . Equal ( pairingVbPib , pairingPibpG2 ) {
if ! bn . Fq12 . Equal ( pairingVbPib , pairingPibpG2 ) {
return false
return false
} else {
} else {
fmt . Println ( "valid knowledge commitment for B" )
fmt . Println ( "✓ e(Vb, piB) == e(piB', g2), valid knowledge commitment for B" )
}
}
// e(piC, Vc) == e(piC', g2)
// e(piC, Vc) == e(piC', g2)
pairingPicVc , err := bn . Pairing ( proof . PiC , setup . Vk . C )
if err != nil {
return false
}
pairingPicpG2 , err := bn . Pairing ( proof . PiCp , bn . G2 . G )
if err != nil {
return false
}
pairingPicVc := bn . Pairing ( proof . PiC , setup . Vk . Vkc )
pairingPicpG2 := bn . Pairing ( proof . PiCp , bn . G2 . G )
if ! bn . Fq12 . Equal ( pairingPicVc , pairingPicpG2 ) {
if ! bn . Fq12 . Equal ( pairingPicVc , pairingPicpG2 ) {
return false
return false
} else {
} else {
fmt . Println ( "valid knowledge commitment for C" )
fmt . Println ( "✓ e(piC, Vc) == e(piC', g2), valid knowledge commitment for C" )
}
}
// Vkx, to then calculate Vkx+piA
// Vkx, to then calculate Vkx+piA
vkxpia := setup . Vk . A [ 0 ]
for i := 0 ; i < circuit . NPublic ; i ++ {
vkxpia = bn . G1 . Add ( vkxpia , bn . G1 . MulScalar ( setup . Vk . A [ i + 1 ] , proof . PublicSignals [ i ] ) )
}
// e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2)
// e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2)
pairingPiaPib , err := bn . Pairing ( proof . PiA , proof . PiB )
if err != nil {
return false
}
pairingPihVkz , err := bn . Pairing ( proof . PiH , setup . Vk . Vkz )
if err != nil {
return false
}
pairingPicG2 , err := bn . Pairing ( proof . PiC , bn . G2 . G )
if err != nil {
return false
}
pairingR := bn . Fq12 . Mul ( pairingPihVkz , pairingPicG2 )
if ! bn . Fq12 . Equal ( pairingPiaPib , pairingR ) {
fmt . Println ( "p4" )
if ! bn . Fq12 . Equal (
bn . Pairing ( bn . G1 . Add ( vkxpia , proof . PiA ) , proof . PiB ) ,
bn . Fq12 . Mul (
bn . Pairing ( proof . PiH , setup . Vk . Vkz ) ,
bn . Pairing ( proof . PiC , bn . G2 . G ) ) ) {
return false
return false
} else {
} else {
fmt . Println ( "QAP disibility checked" )
fmt . Println ( "✓ e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2), QAP disibility checked" )
}
}
// e(piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB)
// e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB)
// == e(piK, g2Kgamma)
// == e(piK, g2Kgamma)
// piApiC := bn.G1.Add(proof.PiA, proof.PiC)
// pairingPiACG2Kbg, err := bn.Pairing(piApiC, setup.Vk.G2Kbg)
// if err != nil {
// return false
// }
// pairingG1KbgPiB, err := bn.Pairing(setup.Vk.G1Kbg, proof.PiB)
// if err != nil {
// return false
// }
// pairingL := bn.Fq12.Mul(pairingPiACG2Kbg, pairingG1KbgPiB)
// pairingR, err := bn.Pairing(proof.PiKp, setup.Vk.G2Kg)
// if err != nil {
// return false
// }
// if !bn.Fq12.Equal(pairingL, pairingR) {
// fmt.Println("p5")
// return false
// }
//
// e(piA, piB) == e(piH, Vz) * e(piC, g2)
// pairingPiaPib, err := bn.Pairing(proof.PiA, proof.PiB)
// if err != nil {
// return false
// }
// pairingPihVz, err := bn.Pairing(proof.PiH, setup.Vk.Vkz)
// if err != nil {
// return false
// }
// pairingPicG2, err := bn.Pairing(proof.PiC, bn.G2.G)
// if err != nil {
// return false
// }
// if !bn.Fq12.Equal(pairingPiaPib, bn.Fq12.Mul(pairingPihVz, pairingPicG2)) {
// return false
// }
piApiC := bn . G1 . Add ( bn . G1 . Add ( vkxpia , proof . PiA ) , proof . PiC )
pairingPiACG2Kbg := bn . Pairing ( piApiC , setup . Vk . G2Kbg )
pairingG1KbgPiB := bn . Pairing ( setup . Vk . G1Kbg , proof . PiB )
pairingL := bn . Fq12 . Mul ( pairingPiACG2Kbg , pairingG1KbgPiB )
pairingR := bn . Pairing ( proof . PiKp , setup . Vk . G2Kg )
if ! bn . Fq12 . Equal ( pairingL , pairingR ) {
return false
} else {
fmt . Println ( "✓ e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB) == e(piK, g2Kgamma)" )
}
return true
return true
}
}