-
-
Save mukeshtiwari/1f4f8b881cf6be95e5eea31325cac66e to your computer and use it in GitHub Desktop.
This project implements Bulletproofs in Go.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package bp | |
import ( | |
"crypto/elliptic" | |
"crypto/rand" | |
"crypto/sha256" | |
"encoding/binary" | |
"math/big" | |
"fmt" | |
"github.com/btcsuite/btcd/btcec" | |
"math" | |
"strconv" | |
) | |
var EC CryptoParams | |
var VecLength = 64 | |
/* | |
Implementation of BulletProofs | |
*/ | |
type ECPoint struct { | |
X, Y *big.Int | |
} | |
// Equal returns true if points p (self) and p2 (arg) are the same. | |
func (p ECPoint) Equal(p2 ECPoint) bool { | |
if p.X.Cmp(p2.X) == 0 && p2.Y.Cmp(p2.Y) == 0 { | |
return true | |
} | |
return false | |
} | |
// Mult multiplies point p by scalar s and returns the resulting point | |
func (p ECPoint) Mult(s *big.Int) ECPoint { | |
modS := new(big.Int).Mod(s, EC.N) | |
X, Y := EC.C.ScalarMult(p.X, p.Y, modS.Bytes()) | |
return ECPoint{X, Y} | |
} | |
// Add adds points p and p2 and returns the resulting point | |
func (p ECPoint) Add(p2 ECPoint) ECPoint { | |
X, Y := EC.C.Add(p.X, p.Y, p2.X, p2.Y) | |
return ECPoint{X, Y} | |
} | |
// Neg returns the additive inverse of point p | |
func (p ECPoint) Neg() ECPoint { | |
negY := new(big.Int).Neg(p.Y) | |
modValue := negY.Mod(negY, EC.C.Params().P) // mod P is fine here because we're describing a curve point | |
return ECPoint{p.X, modValue} | |
} | |
type CryptoParams struct { | |
C elliptic.Curve // curve | |
KC *btcec.KoblitzCurve // curve | |
BPG []ECPoint // slice of gen 1 for BP | |
BPH []ECPoint // slice of gen 2 for BP | |
N *big.Int // scalar prime | |
U ECPoint // a point that is a fixed group element with an unknown discrete-log relative to g,h | |
V int // Vector length | |
G ECPoint // G value for commitments of a single value | |
H ECPoint // H value for commitments of a single value | |
} | |
func (c CryptoParams) Zero() ECPoint { | |
return ECPoint{big.NewInt(0), big.NewInt(0)} | |
} | |
func check(e error) { | |
if e != nil { | |
panic(e) | |
} | |
} | |
/* | |
Vector Pedersen Commitment | |
Given an array of values, we commit the array with different generators | |
for each element and for each randomness. | |
*/ | |
func VectorPCommit(value []*big.Int) (ECPoint, []*big.Int) { | |
R := make([]*big.Int, EC.V) | |
commitment := EC.Zero() | |
for i := 0; i < EC.V; i++ { | |
r, err := rand.Int(rand.Reader, EC.N) | |
check(err) | |
R[i] = r | |
modValue := new(big.Int).Mod(value[i], EC.N) | |
// mG, rH | |
lhsX, lhsY := EC.C.ScalarMult(EC.BPG[i].X, EC.BPG[i].Y, modValue.Bytes()) | |
rhsX, rhsY := EC.C.ScalarMult(EC.BPH[i].X, EC.BPH[i].Y, r.Bytes()) | |
commitment = commitment.Add(ECPoint{lhsX, lhsY}).Add(ECPoint{rhsX, rhsY}) | |
} | |
return commitment, R | |
} | |
/* | |
Two Vector P Commit | |
Given an array of values, we commit the array with different generators | |
for each element and for each randomness. | |
*/ | |
func TwoVectorPCommit(a []*big.Int, b []*big.Int) ECPoint { | |
if len(a) != len(b) { | |
fmt.Println("TwoVectorPCommit: Uh oh! Arrays not of the same length") | |
fmt.Printf("len(a): %d\n", len(a)) | |
fmt.Printf("len(b): %d\n", len(b)) | |
} | |
commitment := EC.Zero() | |
for i := 0; i < EC.V; i++ { | |
commitment = commitment.Add(EC.BPG[i].Mult(a[i])).Add(EC.BPH[i].Mult(b[i])) | |
} | |
return commitment | |
} | |
/* | |
Vector Pedersen Commitment with Gens | |
Given an array of values, we commit the array with different generators | |
for each element and for each randomness. | |
We also pass in the Generators we want to use | |
*/ | |
func TwoVectorPCommitWithGens(G, H []ECPoint, a, b []*big.Int) ECPoint { | |
if len(G) != len(H) || len(G) != len(a) || len(a) != len(b) { | |
fmt.Println("TwoVectorPCommitWithGens: Uh oh! Arrays not of the same length") | |
fmt.Printf("len(G): %d\n", len(G)) | |
fmt.Printf("len(H): %d\n", len(H)) | |
fmt.Printf("len(a): %d\n", len(a)) | |
fmt.Printf("len(b): %d\n", len(b)) | |
} | |
commitment := EC.Zero() | |
for i := 0; i < len(G); i++ { | |
modA := new(big.Int).Mod(a[i], EC.N) | |
modB := new(big.Int).Mod(b[i], EC.N) | |
commitment = commitment.Add(G[i].Mult(modA)).Add(H[i].Mult(modB)) | |
} | |
return commitment | |
} | |
// The length here always has to be a power of two | |
func InnerProduct(a []*big.Int, b []*big.Int) *big.Int { | |
if len(a) != len(b) { | |
fmt.Println("InnerProduct: Uh oh! Arrays not of the same length") | |
fmt.Printf("len(a): %d\n", len(a)) | |
fmt.Printf("len(b): %d\n", len(b)) | |
} | |
c := big.NewInt(0) | |
for i := range a { | |
tmp1 := new(big.Int).Mul(a[i], b[i]) | |
c = new(big.Int).Add(c, new(big.Int).Mod(tmp1, EC.N)) | |
} | |
return new(big.Int).Mod(c, EC.N) | |
} | |
func VectorAdd(v []*big.Int, w []*big.Int) []*big.Int { | |
if len(v) != len(w) { | |
fmt.Println("VectorAdd: Uh oh! Arrays not of the same length") | |
fmt.Printf("len(v): %d\n", len(v)) | |
fmt.Printf("len(w): %d\n", len(w)) | |
} | |
result := make([]*big.Int, len(v)) | |
for i := range v { | |
result[i] = new(big.Int).Mod(new(big.Int).Add(v[i], w[i]), EC.N) | |
} | |
return result | |
} | |
func VectorHadamard(v, w []*big.Int) []*big.Int { | |
if len(v) != len(w) { | |
fmt.Println("VectorHadamard: Uh oh! Arrays not of the same length") | |
fmt.Printf("len(v): %d\n", len(w)) | |
fmt.Printf("len(w): %d\n", len(v)) | |
} | |
result := make([]*big.Int, len(v)) | |
for i := range v { | |
result[i] = new(big.Int).Mod(new(big.Int).Mul(v[i], w[i]), EC.N) | |
} | |
return result | |
} | |
func VectorAddScalar(v []*big.Int, s *big.Int) []*big.Int { | |
result := make([]*big.Int, len(v)) | |
for i := range v { | |
result[i] = new(big.Int).Mod(new(big.Int).Add(v[i], s), EC.N) | |
} | |
return result | |
} | |
func ScalarVectorMul(v []*big.Int, s *big.Int) []*big.Int { | |
result := make([]*big.Int, len(v)) | |
for i := range v { | |
result[i] = new(big.Int).Mod(new(big.Int).Mul(v[i], s), EC.N) | |
} | |
return result | |
} | |
/* | |
InnerProd Proof | |
This stores the argument values | |
*/ | |
type InnerProdArg struct { | |
L []ECPoint | |
R []ECPoint | |
A *big.Int | |
B *big.Int | |
Challenges []*big.Int | |
} | |
func GenerateNewParams(G, H []ECPoint, x *big.Int, L, R, P ECPoint) ([]ECPoint, []ECPoint, ECPoint) { | |
nprime := len(G) / 2 | |
Gprime := make([]ECPoint, nprime) | |
Hprime := make([]ECPoint, nprime) | |
xinv := new(big.Int).ModInverse(x, EC.N) | |
// Gprime = xinv * G[:nprime] + x*G[nprime:] | |
// Hprime = x * H[:nprime] + xinv*H[nprime:] | |
for i := range Gprime { | |
//fmt.Printf("i: %d && i+nprime: %d\n", i, i+nprime) | |
Gprime[i] = G[i].Mult(xinv).Add(G[i+nprime].Mult(x)) | |
Hprime[i] = H[i].Mult(x).Add(H[i+nprime].Mult(xinv)) | |
} | |
x2 := new(big.Int).Mod(new(big.Int).Mul(x, x), EC.N) | |
xinv2 := new(big.Int).ModInverse(x2, EC.N) | |
Pprime := L.Mult(x2).Add(P).Add(R.Mult(xinv2)) // x^2 * L + P + xinv^2 * R | |
return Gprime, Hprime, Pprime | |
} | |
/* Inner Product Argument | |
Proves that <a,b>=c | |
This is a building block for BulletProofs | |
*/ | |
func InnerProductProveSub(proof InnerProdArg, G, H []ECPoint, a []*big.Int, b []*big.Int, u ECPoint, P ECPoint) InnerProdArg { | |
//fmt.Printf("Proof so far: %s\n", proof) | |
if len(a) == 1 { | |
// Prover sends a & b | |
//fmt.Printf("a: %d && b: %d\n", a[0], b[0]) | |
proof.A = a[0] | |
proof.B = b[0] | |
return proof | |
} | |
curIt := int(math.Log2(float64(len(a)))) - 1 | |
nprime := len(a) / 2 | |
//fmt.Println(nprime) | |
//fmt.Println(len(H)) | |
cl := InnerProduct(a[:nprime], b[nprime:]) // either this line | |
cr := InnerProduct(a[nprime:], b[:nprime]) // or this line | |
L := TwoVectorPCommitWithGens(G[nprime:], H[:nprime], a[:nprime], b[nprime:]).Add(u.Mult(cl)) | |
R := TwoVectorPCommitWithGens(G[:nprime], H[nprime:], a[nprime:], b[:nprime]).Add(u.Mult(cr)) | |
proof.L[curIt] = L | |
proof.R[curIt] = R | |
// prover sends L & R and gets a challenge | |
s256 := sha256.Sum256([]byte( | |
L.X.String() + L.Y.String() + | |
R.X.String() + R.Y.String())) | |
x := new(big.Int).SetBytes(s256[:]) | |
proof.Challenges[curIt] = x | |
Gprime, Hprime, Pprime := GenerateNewParams(G, H, x, L, R, P) | |
//fmt.Printf("Prover - Intermediate Pprime value: %s \n", Pprime) | |
xinv := new(big.Int).ModInverse(x, EC.N) | |
// or these two lines | |
aprime := VectorAdd( | |
ScalarVectorMul(a[:nprime], x), | |
ScalarVectorMul(a[nprime:], xinv)) | |
bprime := VectorAdd( | |
ScalarVectorMul(b[:nprime], xinv), | |
ScalarVectorMul(b[nprime:], x)) | |
return InnerProductProveSub(proof, Gprime, Hprime, aprime, bprime, u, Pprime) | |
} | |
//rpresult.IPP = InnerProductProve(left, right, that, P, EC.U, EC.BPG, HPrime) | |
func InnerProductProve(a []*big.Int, b []*big.Int, c *big.Int, P, U ECPoint, G, H []ECPoint) InnerProdArg { | |
loglen := int(math.Log2(float64(len(a)))) | |
challenges := make([]*big.Int, loglen+1) | |
Lvals := make([]ECPoint, loglen) | |
Rvals := make([]ECPoint, loglen) | |
runningProof := InnerProdArg{ | |
Lvals, | |
Rvals, | |
big.NewInt(0), | |
big.NewInt(0), | |
challenges} | |
// randomly generate an x value from public data | |
x := sha256.Sum256([]byte(P.X.String() + P.Y.String())) | |
runningProof.Challenges[loglen] = new(big.Int).SetBytes(x[:]) | |
Pprime := P.Add(U.Mult(new(big.Int).Mul(new(big.Int).SetBytes(x[:]), c))) | |
ux := U.Mult(new(big.Int).SetBytes(x[:])) | |
//fmt.Printf("Prover Pprime value to run sub off of: %s\n", Pprime) | |
return InnerProductProveSub(runningProof, G, H, a, b, ux, Pprime) | |
} | |
/* Inner Product Verify | |
Given a inner product proof, verifies the correctness of the proof | |
Since we're using the Fiat-Shamir transform, we need to verify all x hash computations, | |
all g' and h' computations | |
P : the Pedersen commitment we are verifying is a commitment to the innner product | |
ipp : the proof | |
*/ | |
func InnerProductVerify(c *big.Int, P, U ECPoint, G, H []ECPoint, ipp InnerProdArg) bool { | |
//fmt.Println("Verifying Inner Product Argument") | |
//fmt.Printf("Commitment Value: %s \n", P) | |
s1 := sha256.Sum256([]byte(P.X.String() + P.Y.String())) | |
chal1 := new(big.Int).SetBytes(s1[:]) | |
ux := U.Mult(chal1) | |
curIt := len(ipp.Challenges) - 1 | |
if ipp.Challenges[curIt].Cmp(chal1) != 0 { | |
fmt.Println("IPVerify - Initial Challenge Failed") | |
return false | |
} | |
curIt -= 1 | |
Gprime := G | |
Hprime := H | |
Pprime := P.Add(ux.Mult(c)) // line 6 from protocol 1 | |
//fmt.Printf("New Commitment value with u^cx: %s \n", Pprime) | |
for curIt >= 0 { | |
Lval := ipp.L[curIt] | |
Rval := ipp.R[curIt] | |
// prover sends L & R and gets a challenge | |
s256 := sha256.Sum256([]byte( | |
Lval.X.String() + Lval.Y.String() + | |
Rval.X.String() + Rval.Y.String())) | |
chal2 := new(big.Int).SetBytes(s256[:]) | |
if ipp.Challenges[curIt].Cmp(chal2) != 0 { | |
fmt.Println("IPVerify - Challenge verification failed at index " + strconv.Itoa(curIt)) | |
return false | |
} | |
Gprime, Hprime, Pprime = GenerateNewParams(Gprime, Hprime, chal2, Lval, Rval, Pprime) | |
curIt -= 1 | |
} | |
ccalc := new(big.Int).Mod(new(big.Int).Mul(ipp.A, ipp.B), EC.N) | |
Pcalc1 := Gprime[0].Mult(ipp.A) | |
Pcalc2 := Hprime[0].Mult(ipp.B) | |
Pcalc3 := ux.Mult(ccalc) | |
Pcalc := Pcalc1.Add(Pcalc2).Add(Pcalc3) | |
if !Pprime.Equal(Pcalc) { | |
fmt.Println("IPVerify - Final Commitment checking failed") | |
fmt.Printf("Final Pprime value: %s \n", Pprime) | |
fmt.Printf("Calculated Pprime value to check against: %s \n", Pcalc) | |
return false | |
} | |
return true | |
} | |
/* Inner Product Verify Fast | |
Given a inner product proof, verifies the correctness of the proof. Does the same as above except | |
we replace n separate exponentiations with a single multi-exponentiation. | |
*/ | |
func InnerProductVerifyFast(c *big.Int, P, U ECPoint, G, H []ECPoint, ipp InnerProdArg) bool { | |
//fmt.Println("Verifying Inner Product Argument") | |
//fmt.Printf("Commitment Value: %s \n", P) | |
s1 := sha256.Sum256([]byte(P.X.String() + P.Y.String())) | |
chal1 := new(big.Int).SetBytes(s1[:]) | |
ux := U.Mult(chal1) | |
curIt := len(ipp.Challenges) - 1 | |
// check all challenges | |
if ipp.Challenges[curIt].Cmp(chal1) != 0 { | |
fmt.Println("IPVerify - Initial Challenge Failed") | |
return false | |
} | |
for j := curIt - 1; j >= 0; j-- { | |
Lval := ipp.L[j] | |
Rval := ipp.R[j] | |
// prover sends L & R and gets a challenge | |
s256 := sha256.Sum256([]byte( | |
Lval.X.String() + Lval.Y.String() + | |
Rval.X.String() + Rval.Y.String())) | |
chal2 := new(big.Int).SetBytes(s256[:]) | |
if ipp.Challenges[j].Cmp(chal2) != 0 { | |
fmt.Println("IPVerify - Challenge verification failed at index " + strconv.Itoa(j)) | |
return false | |
} | |
} | |
// begin computing | |
curIt -= 1 | |
Pprime := P.Add(ux.Mult(c)) // line 6 from protocol 1 | |
tmp1 := EC.Zero() | |
for j := curIt; j >= 0; j-- { | |
x2 := new(big.Int).Exp(ipp.Challenges[j], big.NewInt(2), EC.N) | |
x2i := new(big.Int).ModInverse(x2, EC.N) | |
//fmt.Println(tmp1) | |
tmp1 = ipp.L[j].Mult(x2).Add(ipp.R[j].Mult(x2i)).Add(tmp1) | |
//fmt.Println(tmp1) | |
} | |
rhs := Pprime.Add(tmp1) | |
//rhs=P+c*ux + L*xw+R*x2i 公式29 | |
sScalars := make([]*big.Int, EC.V) | |
invsScalars := make([]*big.Int, EC.V) | |
for i := 0; i < EC.V; i++ { | |
si := big.NewInt(1) | |
for j := curIt; j >= 0; j-- { | |
// original challenge if the jth bit of i is 1, inverse challenge otherwise | |
chal := ipp.Challenges[j] | |
if big.NewInt(int64(i)).Bit(j) == 0 { | |
chal = new(big.Int).ModInverse(chal, EC.N) | |
} | |
// fmt.Printf("Challenge raised to value: %d\n", chal) | |
si = new(big.Int).Mod(new(big.Int).Mul(si, chal), EC.N) | |
} | |
//fmt.Printf("Si value: %d\n", si) | |
sScalars[i] = si | |
invsScalars[i] = new(big.Int).ModInverse(si, EC.N) | |
} | |
ccalc := new(big.Int).Mod(new(big.Int).Mul(ipp.A, ipp.B), EC.N) | |
lhs := TwoVectorPCommitWithGens(G, H, ScalarVectorMul(sScalars, ipp.A), ScalarVectorMul(invsScalars, ipp.B)).Add(ux.Mult(ccalc)) | |
if !rhs.Equal(lhs) { | |
fmt.Println("IPVerify - Final Commitment checking failed") | |
fmt.Printf("Final rhs value: %s \n", rhs) | |
fmt.Printf("Final lhs value: %s \n", lhs) | |
return false | |
} | |
return true | |
} | |
// from here: https://play.golang.org/p/zciRZvD0Gr with a fix | |
func PadLeft(str, pad string, l int) string { | |
strCopy := str | |
for len(strCopy) < l { | |
strCopy = pad + strCopy | |
} | |
return strCopy | |
} | |
func STRNot(str string) string { | |
result := "" | |
for _, i := range str { | |
if i == '0' { | |
result += "1" | |
} else { | |
result += "0" | |
} | |
} | |
return result | |
} | |
func StrToBigIntArray(str string) []*big.Int { | |
result := make([]*big.Int, len(str)) | |
for i := range str { | |
t, success := new(big.Int).SetString(string(str[i]), 10) | |
if success { | |
result[i] = t | |
} | |
} | |
return result | |
} | |
func reverse(l []*big.Int) []*big.Int { | |
result := make([]*big.Int, len(l)) | |
for i := range l { | |
result[i] = l[len(l)-i-1] | |
} | |
return result | |
} | |
func PowerVector(l int, base *big.Int) []*big.Int { | |
result := make([]*big.Int, l) | |
for i := 0; i < l; i++ { | |
result[i] = new(big.Int).Exp(base, big.NewInt(int64(i)), EC.N) | |
} | |
return result | |
} | |
func RandVector(l int) []*big.Int { | |
result := make([]*big.Int, l) | |
for i := 0; i < l; i++ { | |
x, err := rand.Int(rand.Reader, EC.N) | |
check(err) | |
result[i] = x | |
} | |
return result | |
} | |
func VectorSum(y []*big.Int) *big.Int { | |
result := big.NewInt(0) | |
for _, j := range y { | |
result = new(big.Int).Mod(new(big.Int).Add(result, j), EC.N) | |
} | |
return result | |
} | |
type RangeProof struct { | |
Comm ECPoint | |
A ECPoint | |
S ECPoint | |
T1 ECPoint | |
T2 ECPoint | |
Tau *big.Int | |
Th *big.Int | |
Mu *big.Int | |
IPP InnerProdArg | |
// challenges | |
Cy *big.Int | |
Cz *big.Int | |
Cx *big.Int | |
} | |
/* | |
Delta is a helper function that is used in the range proof | |
\delta(y, z) = (z-z^2)<1^n, y^n> - z^3<1^n, 2^n> | |
*/ | |
func Delta(y []*big.Int, z *big.Int) *big.Int { | |
result := big.NewInt(0) | |
// (z-z^2)<1^n, y^n> | |
z2 := new(big.Int).Mod(new(big.Int).Mul(z, z), EC.N) | |
t1 := new(big.Int).Mod(new(big.Int).Sub(z, z2), EC.N) | |
t2 := new(big.Int).Mod(new(big.Int).Mul(t1, VectorSum(y)), EC.N) | |
// z^3<1^n, 2^n> | |
z3 := new(big.Int).Mod(new(big.Int).Mul(z2, z), EC.N) | |
po2sum := new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(EC.V)), EC.N), big.NewInt(1)) | |
t3 := new(big.Int).Mod(new(big.Int).Mul(z3, po2sum), EC.N) | |
result = new(big.Int).Mod(new(big.Int).Sub(t2, t3), EC.N) | |
return result | |
} | |
// Calculates (aL - z*1^n) + sL*x | |
func CalculateL(aL, sL []*big.Int, z, x *big.Int) []*big.Int { | |
result := make([]*big.Int, len(aL)) | |
tmp1 := VectorAddScalar(aL, new(big.Int).Neg(z)) | |
tmp2 := ScalarVectorMul(sL, x) | |
result = VectorAdd(tmp1, tmp2) | |
return result | |
} | |
func CalculateR(aR, sR, y, po2 []*big.Int, z, x *big.Int) []*big.Int { | |
if len(aR) != len(sR) || len(aR) != len(y) || len(y) != len(po2) { | |
fmt.Println("CalculateR: Uh oh! Arrays not of the same length") | |
fmt.Printf("len(aR): %d\n", len(aR)) | |
fmt.Printf("len(sR): %d\n", len(sR)) | |
fmt.Printf("len(y): %d\n", len(y)) | |
fmt.Printf("len(po2): %d\n", len(po2)) | |
} | |
result := make([]*big.Int, len(aR)) | |
z2 := new(big.Int).Exp(z, big.NewInt(2), EC.N) | |
tmp11 := VectorAddScalar(aR, z) | |
tmp12 := ScalarVectorMul(sR, x) | |
tmp1 := VectorHadamard(y, VectorAdd(tmp11, tmp12)) | |
tmp2 := ScalarVectorMul(po2, z2) | |
result = VectorAdd(tmp1, tmp2) | |
return result | |
} | |
/* | |
RPProver : Range Proof Prove | |
Given a value v, provides a range proof that v is inside 0 to 2^64-1 | |
*/ | |
func RPProve(v *big.Int) RangeProof { | |
rpresult := RangeProof{} | |
PowerOfTwos := PowerVector(EC.V, big.NewInt(2)) | |
//不能小于最小值 | |
if v.Cmp(big.NewInt(0)) == -1 { | |
panic("Value is below range! Not proving") | |
} | |
//不能大于最大值 | |
if v.Cmp(new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(EC.V)), EC.N)) == 1 { | |
panic("Value is above range! Not proving.") | |
} | |
// 普邓森见证 | |
gamma, err := rand.Int(rand.Reader, EC.N) | |
check(err) | |
comm := EC.G.Mult(v).Add(EC.H.Mult(gamma)) | |
rpresult.Comm = comm | |
//Comm = v*G + gamma*H | |
// break up v into its bitwise representation | |
//aL := 0 | |
//二进制、填充 | |
aL := reverse(StrToBigIntArray(PadLeft(fmt.Sprintf("%b", v), "0", EC.V))) | |
//取反 | |
aR := VectorAddScalar(aL, big.NewInt(-1)) | |
//文档公式35 | |
alpha, err := rand.Int(rand.Reader, EC.N) | |
check(err) | |
A := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, aL, aR).Add(EC.H.Mult(alpha)) | |
rpresult.A = A | |
// 普邓森见证 | |
//A=(a*G + b*H) + alpha*H | |
sL := RandVector(EC.V) | |
sR := RandVector(EC.V) | |
rho, err := rand.Int(rand.Reader, EC.N) | |
check(err) | |
S := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, sL, sR).Add(EC.H.Mult(rho)) | |
rpresult.S = S | |
// 普邓森见证 | |
//S=(a*G + b*H) + rho*H | |
chal1s256 := sha256.Sum256([]byte(A.X.String() + A.Y.String())) | |
cy := new(big.Int).SetBytes(chal1s256[:]) | |
rpresult.Cy = cy | |
//散列哈希 | |
//Cy = sha256(A) | |
chal2s256 := sha256.Sum256([]byte(S.X.String() + S.Y.String())) | |
cz := new(big.Int).SetBytes(chal2s256[:]) | |
rpresult.Cz = cz | |
//散列哈希 | |
//Cz = sha256(S) | |
z2 := new(big.Int).Exp(cz, big.NewInt(2), EC.N) | |
// need to generate l(X), r(X), and t(X)=<l(X),r(X)> | |
/* | |
Java code on how to calculate t1 and t2 | |
FieldVector ys = FieldVector.from(VectorX.iterate(n, BigInteger.ONE, y::multiply),q); //powers of y | |
FieldVector l0 = aL.add(z.negate()); | |
FieldVector l1 = sL; | |
FieldVector twoTimesZSquared = twos.times(zSquared); | |
FieldVector r0 = ys.hadamard(aR.add(z)).add(twoTimesZSquared); | |
FieldVector r1 = sR.hadamard(ys); | |
BigInteger k = ys.sum().multiply(z.subtract(zSquared)).subtract(zCubed.shiftLeft(n).subtract(zCubed)); | |
BigInteger t0 = k.add(zSquared.multiply(number)); | |
BigInteger t1 = l1.innerPoduct(r0).add(l0.innerPoduct(r1)); | |
BigInteger t2 = l1.innerPoduct(r1); | |
PolyCommitment<T> polyCommitment = PolyCommitment.from(base, t0, VectorX.of(t1, t2)); | |
*/ | |
PowerOfCY := PowerVector(EC.V, cy) | |
// fmt.Println(PowerOfCY) | |
l0 := VectorAddScalar(aL, new(big.Int).Neg(cz)) | |
// l1 := sL | |
r0 := VectorAdd( | |
VectorHadamard( | |
PowerOfCY, | |
VectorAddScalar(aR, cz)), | |
ScalarVectorMul( | |
PowerOfTwos, | |
z2)) | |
r1 := VectorHadamard(sR, PowerOfCY) | |
//calculate t0 | |
t0 := new(big.Int).Mod(new(big.Int).Add(new(big.Int).Mul(v, z2), Delta(PowerOfCY, cz)), EC.N) | |
t1 := new(big.Int).Mod(new(big.Int).Add(InnerProduct(sL, r0), InnerProduct(l0, r1)), EC.N) | |
t2 := InnerProduct(sL, r1) | |
// given the t_i values, we can generate commitments to them | |
tau1, err := rand.Int(rand.Reader, EC.N) | |
check(err) | |
tau2, err := rand.Int(rand.Reader, EC.N) | |
check(err) | |
T1 := EC.G.Mult(t1).Add(EC.H.Mult(tau1)) //commitment to t1 | |
T2 := EC.G.Mult(t2).Add(EC.H.Mult(tau2)) //commitment to t2 | |
rpresult.T1 = T1 | |
//普邓森见证 | |
//T1 = t1*G + tau1*H | |
rpresult.T2 = T2 | |
//普邓森见证 | |
//T2 = t2*G + tau2*H | |
chal3s256 := sha256.Sum256([]byte(T1.X.String() + T1.Y.String() + T2.X.String() + T2.Y.String())) | |
cx := new(big.Int).SetBytes(chal3s256[:]) | |
rpresult.Cx = cx | |
//Cx = sha256(T1 + T2) | |
left := CalculateL(aL, sL, cz, cx) | |
right := CalculateR(aR, sR, PowerOfCY, PowerOfTwos, cz, cx) | |
//一个是多项式加,展开的多项式 | |
thatPrime := new(big.Int).Mod( // t(x) = t0 + t1*x + t2*x^2 | |
new(big.Int).Add( | |
t0, | |
new(big.Int).Add( | |
new(big.Int).Mul( | |
t1, cx), | |
new(big.Int).Mul( | |
new(big.Int).Mul(cx, cx), | |
t2))), EC.N) | |
//一个是内积 t(x) = <l(x), r(x)> | |
that := InnerProduct(left, right) // NOTE: BP Java implementation calculates this from the t_i | |
//<l(x), r(x)> = t0 + t1*x + t2*x^2 | |
// thatPrime and that should be equal | |
if thatPrime.Cmp(that) != 0 { | |
fmt.Println("Proving -- Uh oh! Two diff ways to compute same value not working") | |
fmt.Printf("\tthatPrime = %s\n", thatPrime.String()) | |
fmt.Printf("\tthat = %s \n", that.String()) | |
} | |
rpresult.Th = thatPrime | |
//Th = t0 + t1*x + t2*x^2 | |
taux1 := new(big.Int).Mod(new(big.Int).Mul(tau2, new(big.Int).Mul(cx, cx)), EC.N) | |
//t2*x^2 | |
taux2 := new(big.Int).Mod(new(big.Int).Mul(tau1, cx), EC.N) | |
//t1*x | |
taux3 := new(big.Int).Mod(new(big.Int).Mul(z2, gamma), EC.N) | |
//z2*gamma | |
taux := new(big.Int).Mod(new(big.Int).Add(taux1, new(big.Int).Add(taux2, taux3)), EC.N) | |
//taux1+taux2+taux3 | |
rpresult.Tau = taux | |
//Tau = taux1 + taux2 + taux3 | |
mu := new(big.Int).Mod(new(big.Int).Add(alpha, new(big.Int).Mul(rho, cx)), EC.N) | |
rpresult.Mu = mu | |
//Mu = alpha + rho*Cx | |
HPrime := make([]ECPoint, len(EC.BPH)) | |
for i := range HPrime { | |
HPrime[i] = EC.BPH[i].Mult(new(big.Int).ModInverse(PowerOfCY[i], EC.N)) | |
} | |
// for testing | |
tmp1 := EC.Zero() | |
zneg := new(big.Int).Mod(new(big.Int).Neg(cz), EC.N) | |
for i := range EC.BPG { | |
tmp1 = tmp1.Add(EC.BPG[i].Mult(zneg)) | |
} | |
tmp2 := EC.Zero() | |
for i := range HPrime { | |
val1 := new(big.Int).Mul(cz, PowerOfCY[i]) | |
val2 := new(big.Int).Mul(new(big.Int).Mul(cz, cz), PowerOfTwos[i]) | |
tmp2 = tmp2.Add(HPrime[i].Mult(new(big.Int).Add(val1, val2))) | |
} | |
//P1 := A.Add(S.Mult(cx)).Add(tmp1).Add(tmp2).Add(EC.U.Mult(that)).Add(EC.H.Mult(mu).Neg()) | |
P := TwoVectorPCommitWithGens(EC.BPG, HPrime, left, right) | |
//fmt.Println(P1) | |
//fmt.Println(P2) | |
rpresult.IPP = InnerProductProve(left, right, that, P, EC.U, EC.BPG, HPrime) | |
fmt.Printf("rpresult %s \n", rpresult) | |
return rpresult | |
} | |
func RPVerify(rp RangeProof) bool { | |
// verify the challenges | |
chal1s256 := sha256.Sum256([]byte(rp.A.X.String() + rp.A.Y.String())) | |
cy := new(big.Int).SetBytes(chal1s256[:]) | |
if cy.Cmp(rp.Cy) != 0 { | |
fmt.Println("RPVerify - Challenge Cy failing!") | |
return false | |
} | |
chal2s256 := sha256.Sum256([]byte(rp.S.X.String() + rp.S.Y.String())) | |
cz := new(big.Int).SetBytes(chal2s256[:]) | |
if cz.Cmp(rp.Cz) != 0 { | |
fmt.Println("RPVerify - Challenge Cz failing!") | |
return false | |
} | |
chal3s256 := sha256.Sum256([]byte(rp.T1.X.String() + rp.T1.Y.String() + rp.T2.X.String() + rp.T2.Y.String())) | |
cx := new(big.Int).SetBytes(chal3s256[:]) | |
if cx.Cmp(rp.Cx) != 0 { | |
fmt.Println("RPVerify - Challenge Cx failing!") | |
return false | |
} | |
// given challenges are correct, very range proof | |
PowersOfY := PowerVector(EC.V, cy) | |
// t_hat * G + tau * H | |
lhs := EC.G.Mult(rp.Th).Add(EC.H.Mult(rp.Tau)) | |
// z^2 * V + delta(y,z) * G + x * T1 + x^2 * T2 | |
rhs := rp.Comm.Mult(new(big.Int).Mul(cz, cz)).Add( | |
EC.G.Mult(Delta(PowersOfY, cz))).Add( | |
rp.T1.Mult(cx)).Add( | |
rp.T2.Mult(new(big.Int).Mul(cx, cx))) | |
if !lhs.Equal(rhs) { | |
fmt.Println("RPVerify - Uh oh! Check line (63) of verification") | |
fmt.Println(rhs) | |
fmt.Println(lhs) | |
return false | |
} | |
tmp1 := EC.Zero() | |
zneg := new(big.Int).Mod(new(big.Int).Neg(cz), EC.N) | |
for i := range EC.BPG { | |
tmp1 = tmp1.Add(EC.BPG[i].Mult(zneg)) | |
} | |
//tmp1+=BPG*(-cz) | |
PowerOfTwos := PowerVector(EC.V, big.NewInt(2)) | |
tmp2 := EC.Zero() | |
// generate h' | |
HPrime := make([]ECPoint, len(EC.BPH)) | |
for i := range HPrime { | |
mi := new(big.Int).ModInverse(PowersOfY[i], EC.N) | |
HPrime[i] = EC.BPH[i].Mult(mi) | |
} | |
for i := range HPrime { | |
val1 := new(big.Int).Mul(cz, PowersOfY[i]) | |
val2 := new(big.Int).Mul(new(big.Int).Mul(cz, cz), PowerOfTwos[i]) | |
tmp2 = tmp2.Add(HPrime[i].Mult(new(big.Int).Add(val1, val2))) | |
} | |
//tmp2+=BPH*(val1+val2) | |
// without subtracting this value should equal muCH + l[i]G[i] + r[i]H'[i] | |
// we want to make sure that the innerproduct checks out, so we subtract it | |
P := rp.A.Add(rp.S.Mult(cx)).Add(tmp1).Add(tmp2).Add(EC.H.Mult(rp.Mu).Neg()) | |
//fmt.Println(P) | |
//P=A+cx*S+tmp1+tmp2+(-Mu*H) | |
if !InnerProductVerifyFast(rp.Th, P, EC.U, EC.BPG, HPrime, rp.IPP) { | |
fmt.Println("RPVerify - Uh oh! Check line (65) of verification!") | |
return false | |
} | |
return true | |
} | |
// Calculates (aL - z*1^n) + sL*x | |
func CalculateLMRP(aL, sL []*big.Int, z, x *big.Int) []*big.Int { | |
result := make([]*big.Int, len(aL)) | |
tmp1 := VectorAddScalar(aL, new(big.Int).Neg(z)) | |
tmp2 := ScalarVectorMul(sL, x) | |
result = VectorAdd(tmp1, tmp2) | |
return result | |
} | |
func CalculateRMRP(aR, sR, y, zTimesTwo []*big.Int, z, x *big.Int) []*big.Int { | |
if len(aR) != len(sR) || len(aR) != len(y) || len(y) != len(zTimesTwo) { | |
fmt.Println("CalculateR: Uh oh! Arrays not of the same length") | |
fmt.Printf("len(aR): %d\n", len(aR)) | |
fmt.Printf("len(sR): %d\n", len(sR)) | |
fmt.Printf("len(y): %d\n", len(y)) | |
fmt.Printf("len(po2): %d\n", len(zTimesTwo)) | |
} | |
result := make([]*big.Int, len(aR)) | |
tmp11 := VectorAddScalar(aR, z) | |
tmp12 := ScalarVectorMul(sR, x) | |
tmp1 := VectorHadamard(y, VectorAdd(tmp11, tmp12)) | |
result = VectorAdd(tmp1, zTimesTwo) | |
return result | |
} | |
/* | |
DeltaMRP is a helper function that is used in the multi range proof | |
\delta(y, z) = (z-z^2)<1^n, y^n> - \sum_j z^3+j<1^n, 2^n> | |
*/ | |
func DeltaMRP(y []*big.Int, z *big.Int, m int) *big.Int { | |
result := big.NewInt(0) | |
// (z-z^2)<1^n, y^n> | |
z2 := new(big.Int).Mod(new(big.Int).Mul(z, z), EC.N) | |
t1 := new(big.Int).Mod(new(big.Int).Sub(z, z2), EC.N) | |
t2 := new(big.Int).Mod(new(big.Int).Mul(t1, VectorSum(y)), EC.N) | |
// \sum_j z^3+j<1^n, 2^n> | |
// <1^n, 2^n> = 2^n - 1 | |
po2sum := new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(EC.V/m)), EC.N), big.NewInt(1)) | |
t3 := big.NewInt(0) | |
for j := 0; j < m; j++ { | |
zp := new(big.Int).Exp(z, big.NewInt(3+int64(j)), EC.N) | |
tmp1 := new(big.Int).Mod(new(big.Int).Mul(zp, po2sum), EC.N) | |
t3 = new(big.Int).Mod(new(big.Int).Add(t3, tmp1), EC.N) | |
} | |
result = new(big.Int).Mod(new(big.Int).Sub(t2, t3), EC.N) | |
return result | |
} | |
type MultiRangeProof struct { | |
Comms []ECPoint | |
A ECPoint | |
S ECPoint | |
T1 ECPoint | |
T2 ECPoint | |
Tau *big.Int | |
Th *big.Int | |
Mu *big.Int | |
IPP InnerProdArg | |
// challenges | |
Cy *big.Int | |
Cz *big.Int | |
Cx *big.Int | |
} | |
/* | |
MultiRangeProof Prove | |
Takes in a list of values and provides an aggregate | |
range proof for all the values. | |
changes: | |
all values are concatenated | |
r(x) is computed differently | |
tau_x calculation is different | |
delta calculation is different | |
{(g, h \in G, \textbf{V} \in G^m ; \textbf{v, \gamma} \in Z_p^m) : | |
V_j = h^{\gamma_j}g^{v_j} \wedge v_j \in [0, 2^n - 1] \forall j \in [1, m]} | |
*/ | |
func MRPProve(values []*big.Int) MultiRangeProof { | |
// EC.V has the total number of values and bits we can support | |
MRPResult := MultiRangeProof{} | |
m := len(values) | |
bitsPerValue := EC.V / m | |
// we concatenate the binary representation of the values | |
PowerOfTwos := PowerVector(bitsPerValue, big.NewInt(2)) | |
Comms := make([]ECPoint, m) | |
gammas := make([]*big.Int, m) | |
aLConcat := make([]*big.Int, EC.V) | |
aRConcat := make([]*big.Int, EC.V) | |
for j := range values { | |
v := values[j] | |
if v.Cmp(big.NewInt(0)) == -1 { | |
panic("Value is below range! Not proving") | |
} | |
if v.Cmp(new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(bitsPerValue)), EC.N)) == 1 { | |
panic("Value is above range! Not proving.") | |
} | |
gamma, err := rand.Int(rand.Reader, EC.N) | |
check(err) | |
Comms[j] = EC.G.Mult(v).Add(EC.H.Mult(gamma)) | |
gammas[j] = gamma | |
// break up v into its bitwise representation | |
aL := reverse(StrToBigIntArray(PadLeft(fmt.Sprintf("%b", v), "0", bitsPerValue))) | |
aR := VectorAddScalar(aL, big.NewInt(-1)) | |
for i := range aR { | |
aLConcat[bitsPerValue*j+i] = aL[i] | |
aRConcat[bitsPerValue*j+i] = aR[i] | |
} | |
} | |
MRPResult.Comms = Comms | |
alpha, err := rand.Int(rand.Reader, EC.N) | |
check(err) | |
A := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, aLConcat, aRConcat).Add(EC.H.Mult(alpha)) | |
MRPResult.A = A | |
sL := RandVector(EC.V) | |
sR := RandVector(EC.V) | |
rho, err := rand.Int(rand.Reader, EC.N) | |
check(err) | |
S := TwoVectorPCommitWithGens(EC.BPG, EC.BPH, sL, sR).Add(EC.H.Mult(rho)) | |
MRPResult.S = S | |
chal1s256 := sha256.Sum256([]byte(A.X.String() + A.Y.String())) | |
cy := new(big.Int).SetBytes(chal1s256[:]) | |
MRPResult.Cy = cy | |
chal2s256 := sha256.Sum256([]byte(S.X.String() + S.Y.String())) | |
cz := new(big.Int).SetBytes(chal2s256[:]) | |
MRPResult.Cz = cz | |
zPowersTimesTwoVec := make([]*big.Int, EC.V) | |
for j := 0; j < m; j++ { | |
zp := new(big.Int).Exp(cz, big.NewInt(2+int64(j)), EC.N) | |
for i := 0; i < bitsPerValue; i++ { | |
zPowersTimesTwoVec[j*bitsPerValue+i] = new(big.Int).Mod(new(big.Int).Mul(PowerOfTwos[i], zp), EC.N) | |
} | |
} | |
//fmt.Println(zPowersTimesTwoVec) | |
// need to generate l(X), r(X), and t(X)=<l(X),r(X)> | |
/* | |
Java code on how to calculate t1 and t2 | |
//z^Q | |
FieldVector zs = FieldVector.from(VectorX.iterate(m, z.pow(2), z::multiply).map(bi -> bi.mod(q)), q); | |
//2^n | |
VectorX<BigInteger> twoVector = VectorX.iterate(bitsPerNumber, BigInteger.ONE, bi -> bi.shiftLeft(1)); | |
FieldVector twos = FieldVector.from(twoVector, q); | |
//2^n \cdot z || 2^n \cdot z^2 ... | |
FieldVector twoTimesZs = FieldVector.from(zs.getVector().flatMap(twos::times), q); | |
//l(X) | |
FieldVector l0 = aL.add(z.negate()); | |
FieldVector l1 = sL; | |
FieldVectorPolynomial lPoly = new FieldVectorPolynomial(l0, l1); | |
//r(X) | |
FieldVector r0 = ys.hadamard(aR.add(z)).add(twoTimesZs); | |
FieldVector r1 = sR.hadamard(ys); | |
FieldVectorPolynomial rPoly = new FieldVectorPolynomial(r0, r1); | |
*/ | |
PowerOfCY := PowerVector(EC.V, cy) | |
// fmt.Println(PowerOfCY) | |
l0 := VectorAddScalar(aLConcat, new(big.Int).Neg(cz)) | |
l1 := sL | |
r0 := VectorAdd( | |
VectorHadamard( | |
PowerOfCY, | |
VectorAddScalar(aRConcat, cz)), | |
zPowersTimesTwoVec) | |
r1 := VectorHadamard(sR, PowerOfCY) | |
//calculate t0 | |
vz2 := big.NewInt(0) | |
z2 := new(big.Int).Mod(new(big.Int).Mul(cz, cz), EC.N) | |
PowerOfCZ := PowerVector(m, cz) | |
for j := 0; j < m; j++ { | |
vz2 = new(big.Int).Add(vz2, | |
new(big.Int).Mul( | |
PowerOfCZ[j], | |
new(big.Int).Mul(values[j], z2))) | |
vz2 = new(big.Int).Mod(vz2, EC.N) | |
} | |
t0 := new(big.Int).Mod(new(big.Int).Add(vz2, DeltaMRP(PowerOfCY, cz, m)), EC.N) | |
t1 := new(big.Int).Mod(new(big.Int).Add(InnerProduct(l1, r0), InnerProduct(l0, r1)), EC.N) | |
t2 := InnerProduct(l1, r1) | |
// given the t_i values, we can generate commitments to them | |
tau1, err := rand.Int(rand.Reader, EC.N) | |
check(err) | |
tau2, err := rand.Int(rand.Reader, EC.N) | |
check(err) | |
T1 := EC.G.Mult(t1).Add(EC.H.Mult(tau1)) //commitment to t1 | |
T2 := EC.G.Mult(t2).Add(EC.H.Mult(tau2)) //commitment to t2 | |
MRPResult.T1 = T1 | |
MRPResult.T2 = T2 | |
chal3s256 := sha256.Sum256([]byte(T1.X.String() + T1.Y.String() + T2.X.String() + T2.Y.String())) | |
cx := new(big.Int).SetBytes(chal3s256[:]) | |
MRPResult.Cx = cx | |
left := CalculateLMRP(aLConcat, sL, cz, cx) | |
right := CalculateRMRP(aRConcat, sR, PowerOfCY, zPowersTimesTwoVec, cz, cx) | |
thatPrime := new(big.Int).Mod( // t0 + t1*x + t2*x^2 | |
new(big.Int).Add(t0, new(big.Int).Add(new(big.Int).Mul(t1, cx), new(big.Int).Mul(new(big.Int).Mul(cx, cx), t2))), EC.N) | |
that := InnerProduct(left, right) // NOTE: BP Java implementation calculates this from the t_i | |
// thatPrime and that should be equal | |
if thatPrime.Cmp(that) != 0 { | |
fmt.Println("Proving -- Uh oh! Two diff ways to compute same value not working") | |
fmt.Printf("\tthatPrime = %s\n", thatPrime.String()) | |
fmt.Printf("\tthat = %s \n", that.String()) | |
} | |
MRPResult.Th = that | |
vecRandomnessTotal := big.NewInt(0) | |
for j := 0; j < m; j++ { | |
zp := new(big.Int).Exp(cz, big.NewInt(2+int64(j)), EC.N) | |
tmp1 := new(big.Int).Mul(gammas[j], zp) | |
vecRandomnessTotal = new(big.Int).Mod(new(big.Int).Add(vecRandomnessTotal, tmp1), EC.N) | |
} | |
//fmt.Println(vecRandomnessTotal) | |
taux1 := new(big.Int).Mod(new(big.Int).Mul(tau2, new(big.Int).Mul(cx, cx)), EC.N) | |
taux2 := new(big.Int).Mod(new(big.Int).Mul(tau1, cx), EC.N) | |
taux := new(big.Int).Mod(new(big.Int).Add(taux1, new(big.Int).Add(taux2, vecRandomnessTotal)), EC.N) | |
MRPResult.Tau = taux | |
mu := new(big.Int).Mod(new(big.Int).Add(alpha, new(big.Int).Mul(rho, cx)), EC.N) | |
MRPResult.Mu = mu | |
HPrime := make([]ECPoint, len(EC.BPH)) | |
for i := range HPrime { | |
HPrime[i] = EC.BPH[i].Mult(new(big.Int).ModInverse(PowerOfCY[i], EC.N)) | |
} | |
P := TwoVectorPCommitWithGens(EC.BPG, HPrime, left, right) | |
//fmt.Println(P) | |
MRPResult.IPP = InnerProductProve(left, right, that, P, EC.U, EC.BPG, HPrime) | |
return MRPResult | |
} | |
/* | |
MultiRangeProof Verify | |
Takes in a MultiRangeProof and verifies its correctness | |
*/ | |
func MRPVerify(mrp MultiRangeProof) bool { | |
m := len(mrp.Comms) | |
bitsPerValue := EC.V / m | |
//changes: | |
// check 1 changes since it includes all commitments | |
// check 2 commitment generation is also different | |
// verify the challenges | |
chal1s256 := sha256.Sum256([]byte(mrp.A.X.String() + mrp.A.Y.String())) | |
cy := new(big.Int).SetBytes(chal1s256[:]) | |
if cy.Cmp(mrp.Cy) != 0 { | |
fmt.Println("MRPVerify - Challenge Cy failing!") | |
return false | |
} | |
chal2s256 := sha256.Sum256([]byte(mrp.S.X.String() + mrp.S.Y.String())) | |
cz := new(big.Int).SetBytes(chal2s256[:]) | |
if cz.Cmp(mrp.Cz) != 0 { | |
fmt.Println("MRPVerify - Challenge Cz failing!") | |
return false | |
} | |
chal3s256 := sha256.Sum256([]byte(mrp.T1.X.String() + mrp.T1.Y.String() + mrp.T2.X.String() + mrp.T2.Y.String())) | |
cx := new(big.Int).SetBytes(chal3s256[:]) | |
if cx.Cmp(mrp.Cx) != 0 { | |
fmt.Println("RPVerify - Challenge Cx failing!") | |
return false | |
} | |
// given challenges are correct, very range proof | |
PowersOfY := PowerVector(EC.V, cy) | |
// t_hat * G + tau * H | |
lhs := EC.G.Mult(mrp.Th).Add(EC.H.Mult(mrp.Tau)) | |
// z^2 * \bold{z}^m \bold{V} + delta(y,z) * G + x * T1 + x^2 * T2 | |
CommPowers := EC.Zero() | |
PowersOfZ := PowerVector(m, cz) | |
z2 := new(big.Int).Mod(new(big.Int).Mul(cz, cz), EC.N) | |
for j := 0; j < m; j++ { | |
CommPowers = CommPowers.Add(mrp.Comms[j].Mult(new(big.Int).Mul(z2, PowersOfZ[j]))) | |
} | |
rhs := EC.G.Mult(DeltaMRP(PowersOfY, cz, m)).Add( | |
mrp.T1.Mult(cx)).Add( | |
mrp.T2.Mult(new(big.Int).Mul(cx, cx))).Add(CommPowers) | |
if !lhs.Equal(rhs) { | |
fmt.Println("MRPVerify - Uh oh! Check line (63) of verification") | |
fmt.Println(rhs) | |
fmt.Println(lhs) | |
return false | |
} | |
tmp1 := EC.Zero() | |
zneg := new(big.Int).Mod(new(big.Int).Neg(cz), EC.N) | |
for i := range EC.BPG { | |
tmp1 = tmp1.Add(EC.BPG[i].Mult(zneg)) | |
} | |
PowerOfTwos := PowerVector(bitsPerValue, big.NewInt(2)) | |
tmp2 := EC.Zero() | |
// generate h' | |
HPrime := make([]ECPoint, len(EC.BPH)) | |
for i := range HPrime { | |
mi := new(big.Int).ModInverse(PowersOfY[i], EC.N) | |
HPrime[i] = EC.BPH[i].Mult(mi) | |
} | |
for j := 0; j < m; j++ { | |
for i := 0; i < bitsPerValue; i++ { | |
val1 := new(big.Int).Mul(cz, PowersOfY[j*bitsPerValue+i]) | |
zp := new(big.Int).Exp(cz, big.NewInt(2+int64(j)), EC.N) | |
val2 := new(big.Int).Mod(new(big.Int).Mul(zp, PowerOfTwos[i]), EC.N) | |
tmp2 = tmp2.Add(HPrime[j*bitsPerValue+i].Mult(new(big.Int).Add(val1, val2))) | |
} | |
} | |
// without subtracting this value should equal muCH + l[i]G[i] + r[i]H'[i] | |
// we want to make sure that the innerproduct checks out, so we subtract it | |
P := mrp.A.Add(mrp.S.Mult(cx)).Add(tmp1).Add(tmp2).Add(EC.H.Mult(mrp.Mu).Neg()) | |
//fmt.Println(P) | |
if !InnerProductVerifyFast(mrp.Th, P, EC.U, EC.BPG, HPrime, mrp.IPP) { | |
fmt.Println("MRPVerify - Uh oh! Check line (65) of verification!") | |
return false | |
} | |
return true | |
} | |
// NewECPrimeGroupKey returns the curve (field), | |
// Generator 1 x&y, Generator 2 x&y, order of the generators | |
func NewECPrimeGroupKey(n int) CryptoParams { | |
curValue := btcec.S256().Gx | |
s256 := sha256.New() | |
gen1Vals := make([]ECPoint, n) | |
gen2Vals := make([]ECPoint, n) | |
u := ECPoint{big.NewInt(0), big.NewInt(0)} | |
cg := ECPoint{} | |
ch := ECPoint{} | |
j := 0 | |
confirmed := 0 | |
for confirmed < (2*n + 3) { | |
s256.Write(new(big.Int).Add(curValue, big.NewInt(int64(j))).Bytes()) | |
potentialXValue := make([]byte, 33) | |
binary.LittleEndian.PutUint32(potentialXValue, 2) | |
for i, elem := range s256.Sum(nil) { | |
potentialXValue[i+1] = elem | |
} | |
gen2, err := btcec.ParsePubKey(potentialXValue, btcec.S256()) | |
if err == nil { | |
if confirmed == 2*n { // once we've generated all g and h values then assign this to u | |
u = ECPoint{gen2.X, gen2.Y} | |
//fmt.Println("Got that U value") | |
} else if confirmed == 2*n+1 { | |
cg = ECPoint{gen2.X, gen2.Y} | |
} else if confirmed == 2*n+2 { | |
ch = ECPoint{gen2.X, gen2.Y} | |
} else { | |
if confirmed%2 == 0 { | |
gen1Vals[confirmed/2] = ECPoint{gen2.X, gen2.Y} | |
//fmt.Println("new G Value") | |
} else { | |
gen2Vals[confirmed/2] = ECPoint{gen2.X, gen2.Y} | |
//fmt.Println("new H value") | |
} | |
} | |
confirmed += 1 | |
} | |
j += 1 | |
} | |
return CryptoParams{ | |
btcec.S256(), | |
btcec.S256(), | |
gen1Vals, | |
gen2Vals, | |
btcec.S256().N, | |
u, | |
n, | |
cg, | |
ch} | |
} | |
func init() { | |
EC = NewECPrimeGroupKey(VecLength) | |
//fmt.Println(EC) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment