github.com/incognitochain/go-incognito-sdk@v1.0.1/privacy/zkp/aggregaterange/bulletproofs/bulletproofs.go (about)

     1  package bulletproofs
     2  
     3  import (
     4  	"github.com/incognitochain/go-incognito-sdk/privacy"
     5  	"github.com/incognitochain/go-incognito-sdk/privacy/privacy_util"
     6  	"github.com/pkg/errors"
     7  	"math"
     8  )
     9  
    10  type bulletproofParams struct {
    11  	g  []*privacy.Point
    12  	h  []*privacy.Point
    13  	u  *privacy.Point
    14  	cs *privacy.Point
    15  }
    16  
    17  type AggregatedRangeWitness struct {
    18  	values []uint64
    19  	rands  []*privacy.Scalar
    20  }
    21  
    22  type AggregatedRangeProof struct {
    23  	cmsValue          []*privacy.Point
    24  	a                 *privacy.Point
    25  	s                 *privacy.Point
    26  	t1                *privacy.Point
    27  	t2                *privacy.Point
    28  	tauX              *privacy.Scalar
    29  	tHat              *privacy.Scalar
    30  	mu                *privacy.Scalar
    31  	innerProductProof *InnerProductProof
    32  }
    33  
    34  var AggParam = newBulletproofParams(privacy_util.MaxOutputCoin)
    35  
    36  func (proof AggregatedRangeProof) ValidateSanity() bool {
    37  	for i := 0; i < len(proof.cmsValue); i++ {
    38  		if !proof.cmsValue[i].PointValid() {
    39  			return false
    40  		}
    41  	}
    42  	if !proof.a.PointValid() || !proof.s.PointValid() || !proof.t1.PointValid() || !proof.t2.PointValid() {
    43  		return false
    44  	}
    45  	if !proof.tauX.ScalarValid() || !proof.tHat.ScalarValid() || !proof.mu.ScalarValid() {
    46  		return false
    47  	}
    48  
    49  	return proof.innerProductProof.ValidateSanity()
    50  }
    51  
    52  func (proof *AggregatedRangeProof) Init() {
    53  	proof.a = new(privacy.Point).Identity()
    54  	proof.s = new(privacy.Point).Identity()
    55  	proof.t1 = new(privacy.Point).Identity()
    56  	proof.t2 = new(privacy.Point).Identity()
    57  	proof.tauX = new(privacy.Scalar)
    58  	proof.tHat = new(privacy.Scalar)
    59  	proof.mu = new(privacy.Scalar)
    60  	proof.innerProductProof = new(InnerProductProof).Init()
    61  }
    62  
    63  func (proof AggregatedRangeProof) IsNil() bool {
    64  	if proof.a == nil {
    65  		return true
    66  	}
    67  	if proof.s == nil {
    68  		return true
    69  	}
    70  	if proof.t1 == nil {
    71  		return true
    72  	}
    73  	if proof.t2 == nil {
    74  		return true
    75  	}
    76  	if proof.tauX == nil {
    77  		return true
    78  	}
    79  	if proof.tHat == nil {
    80  		return true
    81  	}
    82  	if proof.mu == nil {
    83  		return true
    84  	}
    85  	return proof.innerProductProof == nil
    86  }
    87  
    88  func (proof AggregatedRangeProof) Bytes() []byte {
    89  	var res []byte
    90  
    91  	if proof.IsNil() {
    92  		return []byte{}
    93  	}
    94  
    95  	res = append(res, byte(len(proof.cmsValue)))
    96  	for i := 0; i < len(proof.cmsValue); i++ {
    97  		res = append(res, proof.cmsValue[i].ToBytesS()...)
    98  	}
    99  
   100  	res = append(res, proof.a.ToBytesS()...)
   101  	res = append(res, proof.s.ToBytesS()...)
   102  	res = append(res, proof.t1.ToBytesS()...)
   103  	res = append(res, proof.t2.ToBytesS()...)
   104  
   105  	res = append(res, proof.tauX.ToBytesS()...)
   106  	res = append(res, proof.tHat.ToBytesS()...)
   107  	res = append(res, proof.mu.ToBytesS()...)
   108  	res = append(res, proof.innerProductProof.Bytes()...)
   109  
   110  	return res
   111  }
   112  
   113  func (proof AggregatedRangeProof) GetCommitments() []*privacy.Point {return proof.cmsValue}
   114  
   115  func (proof *AggregatedRangeProof) SetCommitments(cmsValue []*privacy.Point) {
   116  	proof.cmsValue = cmsValue
   117  }
   118  
   119  func (proof *AggregatedRangeProof) SetBytes(bytes []byte) error {
   120  	if len(bytes) == 0 {
   121  		return nil
   122  	}
   123  
   124  	lenValues := int(bytes[0])
   125  	offset := 1
   126  	var err error
   127  
   128  	proof.cmsValue = make([]*privacy.Point, lenValues)
   129  	for i := 0; i < lenValues; i++ {
   130  		if offset+privacy.Ed25519KeySize > len(bytes){
   131  			return errors.New("Range Proof unmarshaling from bytes failed")
   132  		}
   133  		proof.cmsValue[i], err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   134  		if err != nil {
   135  			return err
   136  		}
   137  		offset += privacy.Ed25519KeySize
   138  	}
   139  
   140  	if offset+privacy.Ed25519KeySize > len(bytes){
   141  		return errors.New("Range Proof unmarshaling from bytes failed")
   142  	}
   143  	proof.a, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   144  	if err != nil {
   145  		return err
   146  	}
   147  	offset += privacy.Ed25519KeySize
   148  
   149  	if offset+privacy.Ed25519KeySize > len(bytes){
   150  		return errors.New("Range Proof unmarshaling from bytes failed")
   151  	}
   152  	proof.s, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   153  	if err != nil {
   154  		return err
   155  	}
   156  	offset += privacy.Ed25519KeySize
   157  
   158  	if offset+privacy.Ed25519KeySize > len(bytes){
   159  		return errors.New("Range Proof unmarshaling from bytes failed")
   160  	}
   161  	proof.t1, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   162  	if err != nil {
   163  		return err
   164  	}
   165  	offset += privacy.Ed25519KeySize
   166  
   167  	if offset+privacy.Ed25519KeySize > len(bytes){
   168  		return errors.New("Range Proof unmarshaling from bytes failed")
   169  	}
   170  	proof.t2, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   171  	if err != nil {
   172  		return err
   173  	}
   174  	offset += privacy.Ed25519KeySize
   175  
   176  	if offset+privacy.Ed25519KeySize > len(bytes){
   177  		return errors.New("Range Proof unmarshaling from bytes failed")
   178  	}
   179  	proof.tauX = new(privacy.Scalar).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   180  	offset += privacy.Ed25519KeySize
   181  
   182  	if offset+privacy.Ed25519KeySize > len(bytes){
   183  		return errors.New("Range Proof unmarshaling from bytes failed")
   184  	}
   185  	proof.tHat = new(privacy.Scalar).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   186  	offset += privacy.Ed25519KeySize
   187  
   188  	if offset+privacy.Ed25519KeySize > len(bytes){
   189  		return errors.New("Range Proof unmarshaling from bytes failed")
   190  	}
   191  	proof.mu = new(privacy.Scalar).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   192  	offset += privacy.Ed25519KeySize
   193  
   194  	if offset >= len(bytes){
   195  		return errors.New("Range Proof unmarshaling from bytes failed")
   196  	}
   197  
   198  	proof.innerProductProof = new(InnerProductProof)
   199  	err = proof.innerProductProof.SetBytes(bytes[offset:])
   200  	// it's the last check, so we just return it
   201  	//privacy.Logger.Log.Debugf("AFTER SETBYTES ------------ %v\n", proof.Bytes())
   202  	return err
   203  }
   204  
   205  func (wit *AggregatedRangeWitness) Set(values []uint64, rands []*privacy.Scalar) {
   206  	numValue := len(values)
   207  	wit.values = make([]uint64, numValue)
   208  	wit.rands = make([]*privacy.Scalar, numValue)
   209  
   210  	for i := range values {
   211  		wit.values[i] = values[i]
   212  		wit.rands[i] = new(privacy.Scalar).Set(rands[i])
   213  	}
   214  }
   215  
   216  func (wit AggregatedRangeWitness) Prove() (*AggregatedRangeProof, error) {
   217  	proof := new(AggregatedRangeProof)
   218  	numValue := len(wit.values)
   219  	if numValue > privacy_util.MaxOutputCoin {
   220  		return nil, errors.New("Must less than MaxOutputCoin")
   221  	}
   222  	numValuePad := roundUpPowTwo(numValue)
   223  	maxExp := privacy_util.MaxExp
   224  	N := maxExp * numValuePad
   225  
   226  	aggParam := setAggregateParams(N)
   227  
   228  	values := make([]uint64, numValuePad)
   229  	rands := make([]*privacy.Scalar, numValuePad)
   230  	for i := range wit.values {
   231  		values[i] = wit.values[i]
   232  		rands[i] = new(privacy.Scalar).Set(wit.rands[i])
   233  	}
   234  	for i := numValue; i < numValuePad; i++ {
   235  		values[i] = uint64(0)
   236  		rands[i] = new(privacy.Scalar).FromUint64(0)
   237  	}
   238  
   239  	proof.cmsValue = make([]*privacy.Point, numValue)
   240  	for i := 0; i < numValue; i++ {
   241  		proof.cmsValue[i] = privacy.PedCom.CommitAtIndex(new(privacy.Scalar).FromUint64(values[i]), rands[i], privacy.PedersenValueIndex)
   242  	}
   243  	// Convert values to binary array
   244  	aL := make([]*privacy.Scalar, N)
   245  	aR := make([]*privacy.Scalar, N)
   246  	sL := make([]*privacy.Scalar, N)
   247  	sR := make([]*privacy.Scalar, N)
   248  
   249  	for i, value := range values {
   250  		tmp := ConvertUint64ToBinary(value, maxExp)
   251  		for j := 0; j < maxExp; j++ {
   252  			aL[i*maxExp+j] = tmp[j]
   253  			aR[i*maxExp+j] = new(privacy.Scalar).Sub(tmp[j], new(privacy.Scalar).FromUint64(1))
   254  			sL[i*maxExp+j] = privacy.RandomScalar()
   255  			sR[i*maxExp+j] = privacy.RandomScalar()
   256  		}
   257  	}
   258  	// LINE 40-50
   259  	// Commitment to aL, aR: A = h^alpha * G^aL * H^aR
   260  	// Commitment to sL, sR : S = h^rho * G^sL * H^sR
   261  	var alpha, rho *privacy.Scalar
   262  	if A, err := encodeVectors(aL, aR, aggParam.g, aggParam.h); err != nil {
   263  		return nil, err
   264  	} else if S, err := encodeVectors(sL, sR, aggParam.g, aggParam.h); err != nil {
   265  		return nil, err
   266  	} else {
   267  		alpha = privacy.RandomScalar()
   268  		rho = privacy.RandomScalar()
   269  		A.Add(A, new(privacy.Point).ScalarMult(privacy.HBase, alpha))
   270  		S.Add(S, new(privacy.Point).ScalarMult(privacy.HBase, rho))
   271  		proof.a = A
   272  		proof.s = S
   273  	}
   274  	// challenge y, z
   275  	y := generateChallenge(aggParam.cs.ToBytesS(), []*privacy.Point{proof.a, proof.s})
   276  	z := generateChallenge(y.ToBytesS(), []*privacy.Point{proof.a, proof.s})
   277  
   278  	// LINE 51-54
   279  	twoNumber := new(privacy.Scalar).FromUint64(2)
   280  	twoVectorN := powerVector(twoNumber, maxExp)
   281  
   282  	// HPrime = H^(y^(1-i)
   283  	HPrime := computeHPrime(y, N, aggParam.h)
   284  
   285  	// l(X) = (aL -z*1^n) + sL*X; r(X) = y^n hada (aR +z*1^n + sR*X) + z^2 * 2^n
   286  	yVector := powerVector(y, N)
   287  	hadaProduct, err := hadamardProduct(yVector, vectorAddScalar(aR, z))
   288  	if err != nil {
   289  		return nil, err
   290  	}
   291  	vectorSum := make([]*privacy.Scalar, N)
   292  	zTmp := new(privacy.Scalar).Set(z)
   293  	for j := 0; j < numValuePad; j++ {
   294  		zTmp.Mul(zTmp, z)
   295  		for i := 0; i < maxExp; i++ {
   296  			vectorSum[j*maxExp+i] = new(privacy.Scalar).Mul(twoVectorN[i], zTmp)
   297  		}
   298  	}
   299  	zNeg := new(privacy.Scalar).Sub(new(privacy.Scalar).FromUint64(0), z)
   300  	l0 := vectorAddScalar(aL, zNeg)
   301  	l1 := sL
   302  	var r0, r1 []*privacy.Scalar
   303  	if r0, err = vectorAdd(hadaProduct, vectorSum); err != nil {
   304  		return nil, err
   305  	} else {
   306  		if r1, err = hadamardProduct(yVector, sR); err != nil {
   307  			return nil, err
   308  		}
   309  	}
   310  
   311  	// t(X) = <l(X), r(X)> = t0 + t1*X + t2*X^2
   312  	// t1 = <l1, ro> + <l0, r1>, t2 = <l1, r1>
   313  	var t1, t2 *privacy.Scalar
   314  	if ip3, err := innerProduct(l1, r0); err != nil {
   315  		return nil, err
   316  	} else if ip4, err := innerProduct(l0, r1); err != nil {
   317  		return nil, err
   318  	} else {
   319  		t1 = new(privacy.Scalar).Add(ip3, ip4)
   320  		if t2, err = innerProduct(l1, r1); err != nil {
   321  			return nil, err
   322  		}
   323  	}
   324  
   325  	// commitment to t1, t2
   326  	tau1 := privacy.RandomScalar()
   327  	tau2 := privacy.RandomScalar()
   328  	proof.t1 = privacy.PedCom.CommitAtIndex(t1, tau1, privacy.PedersenValueIndex)
   329  	proof.t2 = privacy.PedCom.CommitAtIndex(t2, tau2, privacy.PedersenValueIndex)
   330  
   331  	x := generateChallenge(z.ToBytesS(), []*privacy.Point{proof.t1, proof.t2})
   332  	xSquare := new(privacy.Scalar).Mul(x, x)
   333  
   334  	// lVector = aL - z*1^n + sL*x
   335  	// rVector = y^n hada (aR +z*1^n + sR*x) + z^2*2^n
   336  	// tHat = <lVector, rVector>
   337  	lVector, err := vectorAdd(vectorAddScalar(aL, zNeg), vectorMulScalar(sL, x))
   338  	if err != nil {
   339  		return nil, err
   340  	}
   341  	tmpVector, err := vectorAdd(vectorAddScalar(aR, z), vectorMulScalar(sR, x))
   342  	if err != nil {
   343  		return nil, err
   344  	}
   345  	rVector, err := hadamardProduct(yVector, tmpVector)
   346  	if err != nil {
   347  		return nil, err
   348  	}
   349  	rVector, err = vectorAdd(rVector, vectorSum)
   350  	if err != nil {
   351  		return nil, err
   352  	}
   353  	proof.tHat, err = innerProduct(lVector, rVector)
   354  	if err != nil {
   355  		return nil, err
   356  	}
   357  
   358  	// blinding value for tHat: tauX = tau2*x^2 + tau1*x + z^2*rand
   359  	proof.tauX = new(privacy.Scalar).Mul(tau2, xSquare)
   360  	proof.tauX.Add(proof.tauX, new(privacy.Scalar).Mul(tau1, x))
   361  	zTmp = new(privacy.Scalar).Set(z)
   362  	tmpBN := new(privacy.Scalar)
   363  	for j := 0; j < numValuePad; j++ {
   364  		zTmp.Mul(zTmp, z)
   365  		proof.tauX.Add(proof.tauX, tmpBN.Mul(zTmp, rands[j]))
   366  	}
   367  
   368  	// alpha, rho blind A, S
   369  	// mu = alpha + rho*x
   370  	proof.mu = new(privacy.Scalar).Add(alpha, new(privacy.Scalar).Mul(rho, x))
   371  
   372  	// instead of sending left vector and right vector, we use inner sum argument to reduce proof size from 2*n to 2(log2(n)) + 2
   373  	innerProductWit := new(InnerProductWitness)
   374  	innerProductWit.a = lVector
   375  	innerProductWit.b = rVector
   376  	innerProductWit.p, err = encodeVectors(lVector, rVector, aggParam.g, HPrime)
   377  	if err != nil {
   378  		return nil, err
   379  	}
   380  	uPrime := new(privacy.Point).ScalarMult(aggParam.u, privacy.HashToScalar(x.ToBytesS()))
   381  	innerProductWit.p = innerProductWit.p.Add(innerProductWit.p, new(privacy.Point).ScalarMult(uPrime, proof.tHat))
   382  
   383  	proof.innerProductProof, err = innerProductWit.Prove(aggParam.g, HPrime, uPrime, x.ToBytesS())
   384  	if err != nil {
   385  		return nil, err
   386  	}
   387  
   388  	return proof, nil
   389  }
   390  
   391  func (proof AggregatedRangeProof) Verify() (bool, error) {
   392  	numValue := len(proof.cmsValue)
   393  	if numValue > privacy_util.MaxOutputCoin {
   394  		return false, errors.New("Must less than MaxOutputNumber")
   395  	}
   396  	numValuePad := roundUpPowTwo(numValue)
   397  	maxExp := privacy_util.MaxExp
   398  	N := numValuePad * maxExp
   399  	twoVectorN := powerVector(new(privacy.Scalar).FromUint64(2), maxExp)
   400  	aggParam := setAggregateParams(N)
   401  
   402  	cmsValue := proof.cmsValue
   403  	for i := numValue; i < numValuePad; i++ {
   404  		cmsValue = append(cmsValue, new(privacy.Point).Identity())
   405  	}
   406  
   407  	// recalculate challenge y, z
   408  	y := generateChallenge(aggParam.cs.ToBytesS(), []*privacy.Point{proof.a, proof.s})
   409  	z := generateChallenge(y.ToBytesS(), []*privacy.Point{proof.a, proof.s})
   410  	zSquare := new(privacy.Scalar).Mul(z, z)
   411  	zNeg := new(privacy.Scalar).Sub(new(privacy.Scalar).FromUint64(0), z)
   412  
   413  	x := generateChallenge(z.ToBytesS(), []*privacy.Point{proof.t1, proof.t2})
   414  	xSquare := new(privacy.Scalar).Mul(x, x)
   415  
   416  	// HPrime = H^(y^(1-i)
   417  	HPrime := computeHPrime(y, N, aggParam.h)
   418  
   419  	// g^tHat * h^tauX = V^(z^2) * g^delta(y,z) * T1^x * T2^(x^2)
   420  	yVector := powerVector(y, N)
   421  	deltaYZ, err := computeDeltaYZ(z, zSquare, yVector, N)
   422  	if err != nil {
   423  		return false, err
   424  	}
   425  
   426  	LHS := privacy.PedCom.CommitAtIndex(proof.tHat, proof.tauX, privacy.PedersenValueIndex)
   427  	RHS := new(privacy.Point).ScalarMult(proof.t2, xSquare)
   428  	RHS.Add(RHS, new(privacy.Point).AddPedersen(deltaYZ, privacy.PedCom.G[privacy.PedersenValueIndex], x, proof.t1))
   429  
   430  	expVector := vectorMulScalar(powerVector(z, numValuePad), zSquare)
   431  	RHS.Add(RHS, new(privacy.Point).MultiScalarMult(expVector, cmsValue))
   432  
   433  	if !privacy.IsPointEqual(LHS, RHS) {
   434  		//privacy.Logger.Log.Errorf("verify aggregated range proof statement 1 failed")
   435  		return false, errors.New("verify aggregated range proof statement 1 failed")
   436  	}
   437  
   438  	// verify eq (66)
   439  	uPrime := new(privacy.Point).ScalarMult(aggParam.u, privacy.HashToScalar(x.ToBytesS()))
   440  
   441  	vectorSum := make([]*privacy.Scalar, N)
   442  	zTmp := new(privacy.Scalar).Set(z)
   443  	for j := 0; j < numValuePad; j++ {
   444  		zTmp.Mul(zTmp, z)
   445  		for i := 0; i < maxExp; i++ {
   446  			vectorSum[j*maxExp+i] = new(privacy.Scalar).Mul(twoVectorN[i], zTmp)
   447  			vectorSum[j*maxExp+i].Add(vectorSum[j*maxExp+i], new(privacy.Scalar).Mul(z, yVector[j*maxExp+i]))
   448  		}
   449  	}
   450  	tmpHPrime := new(privacy.Point).MultiScalarMult(vectorSum, HPrime)
   451  	tmpG := new(privacy.Point).Set(aggParam.g[0])
   452  	for i:= 1; i < N; i++ {
   453  		tmpG.Add(tmpG, aggParam.g[i])
   454  	}
   455  	ASx := new(privacy.Point).Add(proof.a, new(privacy.Point).ScalarMult(proof.s, x))
   456  	P := new(privacy.Point).Add(new(privacy.Point).ScalarMult(tmpG, zNeg), tmpHPrime)
   457  	P.Add(P, ASx)
   458  	P.Add(P, new(privacy.Point).ScalarMult(uPrime, proof.tHat))
   459  	PPrime := new(privacy.Point).Add(proof.innerProductProof.p, new(privacy.Point).ScalarMult(privacy.HBase, proof.mu) )
   460  
   461  	if !privacy.IsPointEqual(P, PPrime) {
   462  		//privacy.Logger.Log.Errorf("verify aggregated range proof statement 2-1 failed")
   463  		return false, errors.New("verify aggregated range proof statement 2-1 failed")
   464  	}
   465  
   466  	// verify eq (68)
   467  	innerProductArgValid := proof.innerProductProof.Verify(aggParam.g, HPrime, uPrime, x.ToBytesS())
   468  	if !innerProductArgValid {
   469  		//privacy.Logger.Log.Errorf("verify aggregated range proof statement 2 failed")
   470  		return false, errors.New("verify aggregated range proof statement 2 failed")
   471  	}
   472  
   473  	return true, nil
   474  }
   475  
   476  func (proof AggregatedRangeProof) VerifyFaster() (bool, error) {
   477  	numValue := len(proof.cmsValue)
   478  	if numValue > privacy_util.MaxOutputCoin {
   479  		return false, errors.New("Must less than MaxOutputNumber")
   480  	}
   481  	numValuePad := roundUpPowTwo(numValue)
   482  	maxExp := privacy_util.MaxExp
   483  	N := maxExp * numValuePad
   484  	aggParam := setAggregateParams(N)
   485  	twoVectorN := powerVector(new(privacy.Scalar).FromUint64(2), maxExp)
   486  
   487  	cmsValue := proof.cmsValue
   488  	for i := numValue; i < numValuePad; i++ {
   489  		cmsValue = append(cmsValue, new(privacy.Point).Identity())
   490  	}
   491  
   492  	// recalculate challenge y, z
   493  	y := generateChallenge(aggParam.cs.ToBytesS(), []*privacy.Point{proof.a, proof.s})
   494  	z := generateChallenge(y.ToBytesS(), []*privacy.Point{proof.a, proof.s})
   495  	zSquare := new(privacy.Scalar).Mul(z, z)
   496  	zNeg := new(privacy.Scalar).Sub(new(privacy.Scalar).FromUint64(0), z)
   497  
   498  	x := generateChallenge(z.ToBytesS(), []*privacy.Point{proof.t1, proof.t2})
   499  	xSquare := new(privacy.Scalar).Mul(x, x)
   500  
   501  	// g^tHat * h^tauX = V^(z^2) * g^delta(y,z) * T1^x * T2^(x^2)
   502  	yVector := powerVector(y, N)
   503  	deltaYZ, err := computeDeltaYZ(z, zSquare, yVector, N)
   504  	if err != nil {
   505  		return false, err
   506  	}
   507  	// HPrime = H^(y^(1-i)
   508  	HPrime := computeHPrime(y, N, aggParam.h)
   509  	uPrime := new(privacy.Point).ScalarMult(aggParam.u, privacy.HashToScalar(x.ToBytesS()))
   510  
   511  
   512  	// Verify eq (65)
   513  	LHS := privacy.PedCom.CommitAtIndex(proof.tHat, proof.tauX, privacy.PedersenValueIndex)
   514  	RHS := new(privacy.Point).ScalarMult(proof.t2, xSquare)
   515  	RHS.Add(RHS, new(privacy.Point).AddPedersen(deltaYZ, privacy.PedCom.G[privacy.PedersenValueIndex], x, proof.t1))
   516  	expVector := vectorMulScalar(powerVector(z, numValuePad), zSquare)
   517  	RHS.Add(RHS, new(privacy.Point).MultiScalarMult(expVector, cmsValue))
   518  	if !privacy.IsPointEqual(LHS, RHS) {
   519  		//privacy.Logger.Log.Errorf("verify aggregated range proof statement 1 failed")
   520  		return false, errors.New("verify aggregated range proof statement 1 failed")
   521  	}
   522  
   523  	// Verify eq (66)
   524  	vectorSum := make([]*privacy.Scalar, N)
   525  	zTmp := new(privacy.Scalar).Set(z)
   526  	for j := 0; j < numValuePad; j++ {
   527  		zTmp.Mul(zTmp, z)
   528  		for i := 0; i < maxExp; i++ {
   529  			vectorSum[j*maxExp+i] = new(privacy.Scalar).Mul(twoVectorN[i], zTmp)
   530  			vectorSum[j*maxExp+i].Add(vectorSum[j*maxExp+i], new(privacy.Scalar).Mul(z, yVector[j*maxExp+i]))
   531  		}
   532  	}
   533  	tmpHPrime := new(privacy.Point).MultiScalarMult(vectorSum, HPrime)
   534  	tmpG := new(privacy.Point).Set(aggParam.g[0])
   535  	for i:= 1; i < N; i++ {
   536  		tmpG.Add(tmpG, aggParam.g[i])
   537  	}
   538  	ASx := new(privacy.Point).Add(proof.a, new(privacy.Point).ScalarMult(proof.s, x))
   539  	P := new(privacy.Point).Add(new(privacy.Point).ScalarMult(tmpG, zNeg), tmpHPrime)
   540  	P.Add(P, ASx)
   541  	P.Add(P, new(privacy.Point).ScalarMult(uPrime, proof.tHat))
   542  	PPrime := new(privacy.Point).Add(proof.innerProductProof.p, new(privacy.Point).ScalarMult(privacy.HBase, proof.mu) )
   543  
   544  	if !privacy.IsPointEqual(P, PPrime) {
   545  		//privacy.Logger.Log.Errorf("verify aggregated range proof statement 2-1 failed")
   546  		return false, errors.New("verify aggregated range proof statement 2-1 failed")
   547  	}
   548  
   549  	// Verify eq (68)
   550  	hashCache := x.ToBytesS()
   551  	L := proof.innerProductProof.l
   552  	R := proof.innerProductProof.r
   553  	s := make([]*privacy.Scalar, N)
   554  	sInverse := make([]*privacy.Scalar, N)
   555  	logN := int(math.Log2(float64(N)))
   556  	vSquareList := make([]*privacy.Scalar, logN)
   557  	vInverseSquareList := make([]*privacy.Scalar, logN)
   558  
   559  	for i := 0; i < N; i++ {
   560  		s[i] = new(privacy.Scalar).Set(proof.innerProductProof.a)
   561  		sInverse[i] = new(privacy.Scalar).Set(proof.innerProductProof.b)
   562  	}
   563  
   564  	for i := range L {
   565  		v := generateChallenge(hashCache, []*privacy.Point{L[i], R[i]})
   566  		hashCache = v.ToBytesS()
   567  		vInverse := new(privacy.Scalar).Invert(v)
   568  		vSquareList[i] = new(privacy.Scalar).Mul(v, v)
   569  		vInverseSquareList[i] = new(privacy.Scalar).Mul(vInverse, vInverse)
   570  
   571  		for j := 0; j < N; j++ {
   572  			if j&int(math.Pow(2, float64(logN-i-1))) != 0 {
   573  				s[j] = new(privacy.Scalar).Mul(s[j], v)
   574  				sInverse[j] = new(privacy.Scalar).Mul(sInverse[j], vInverse)
   575  			} else {
   576  				s[j] = new(privacy.Scalar).Mul(s[j], vInverse)
   577  				sInverse[j] = new(privacy.Scalar).Mul(sInverse[j], v)
   578  			}
   579  		}
   580  	}
   581  
   582  	c := new(privacy.Scalar).Mul(proof.innerProductProof.a, proof.innerProductProof.b)
   583  	tmp1 := new(privacy.Point).MultiScalarMult(s, aggParam.g)
   584  	tmp2 := new(privacy.Point).MultiScalarMult(sInverse, HPrime)
   585  	rightHS := new(privacy.Point).Add(tmp1, tmp2)
   586  	rightHS.Add(rightHS, new(privacy.Point).ScalarMult(uPrime, c))
   587  
   588  	tmp3 := new(privacy.Point).MultiScalarMult(vSquareList, L)
   589  	tmp4 := new(privacy.Point).MultiScalarMult(vInverseSquareList, R)
   590  	leftHS := new(privacy.Point).Add(tmp3, tmp4)
   591  	leftHS.Add(leftHS, proof.innerProductProof.p)
   592  
   593  	res := privacy.IsPointEqual(rightHS, leftHS)
   594  	if !res {
   595  		//privacy.Logger.Log.Errorf("verify aggregated range proof statement 2 failed")
   596  		return false, errors.New("verify aggregated range proof statement 2 failed")
   597  	}
   598  
   599  	return true, nil
   600  }
   601  
   602  func VerifyBatch(proofs []*AggregatedRangeProof) (bool, error, int) {
   603  	maxExp := privacy_util.MaxExp
   604  	baseG := privacy.PedCom.G[privacy.PedersenValueIndex]
   605  	baseH := privacy.PedCom.G[privacy.PedersenRandomnessIndex]
   606  
   607  	sum_tHat := new(privacy.Scalar).FromUint64(0)
   608  	sum_tauX := new(privacy.Scalar).FromUint64(0)
   609  	list_x_alpha := make([]*privacy.Scalar, 0)
   610  	list_x_beta := make([]*privacy.Scalar, 0)
   611  	list_xSquare := make([]*privacy.Scalar, 0)
   612  	list_zSquare := make([]*privacy.Scalar, 0)
   613  
   614  	list_t1 := make([]*privacy.Point, 0)
   615  	list_t2 := make([]*privacy.Point, 0)
   616  	list_V := make([]*privacy.Point, 0)
   617  
   618  	sum_mu := new(privacy.Scalar).FromUint64(0)
   619  	sum_absubthat := new(privacy.Scalar).FromUint64(0)
   620  
   621  	list_S := make([]*privacy.Point, 0)
   622  	list_A := make([]*privacy.Point, 0)
   623  	list_beta := make([]*privacy.Scalar, 0)
   624  	list_LR := make([]*privacy.Point, 0)
   625  	list_lVector := make([]*privacy.Scalar, 0)
   626  	list_rVector := make([]*privacy.Scalar, 0)
   627  	list_gVector := make([]*privacy.Point, 0)
   628  	list_hVector := make([]*privacy.Point, 0)
   629  
   630  	twoNumber := new(privacy.Scalar).FromUint64(2)
   631  	twoVectorN := powerVector(twoNumber, maxExp)
   632  
   633  	for k, proof := range proofs {
   634  		numValue := len(proof.cmsValue)
   635  		if numValue > privacy_util.MaxOutputCoin {
   636  			return false, errors.New("Must less than MaxOutputNumber"), k
   637  		}
   638  		numValuePad := roundUpPowTwo(numValue)
   639  		N := maxExp * numValuePad
   640  		aggParam := setAggregateParams(N)
   641  
   642  		cmsValue := proof.cmsValue
   643  		for i := numValue; i < numValuePad; i++ {
   644  			identity := new(privacy.Point).Identity()
   645  			cmsValue = append(cmsValue, identity)
   646  		}
   647  
   648  		// recalculate challenge y, z, x
   649  		y := generateChallenge(aggParam.cs.ToBytesS(), []*privacy.Point{proof.a, proof.s})
   650  		z := generateChallenge(y.ToBytesS(), []*privacy.Point{proof.a, proof.s})
   651  		x := generateChallenge(z.ToBytesS(), []*privacy.Point{proof.t1, proof.t2})
   652  		zSquare := new(privacy.Scalar).Mul(z, z)
   653  		xSquare := new(privacy.Scalar).Mul(x, x)
   654  
   655  		// Random alpha and beta for batch equations check
   656  		alpha := privacy.RandomScalar()
   657  		beta := privacy.RandomScalar()
   658  		list_beta = append(list_beta, beta)
   659  
   660  		// Compute first equation check
   661  		yVector := powerVector(y, N)
   662  		deltaYZ, err := computeDeltaYZ(z, zSquare, yVector, N)
   663  		if err != nil {
   664  			return false, err, k
   665  		}
   666  		sum_tHat.Add(sum_tHat, new(privacy.Scalar).Mul(alpha, new(privacy.Scalar).Sub(proof.tHat, deltaYZ)))
   667  		sum_tauX.Add(sum_tauX, new(privacy.Scalar).Mul(alpha, proof.tauX))
   668  
   669  		list_x_alpha = append(list_x_alpha, new(privacy.Scalar).Mul(x, alpha))
   670  		list_x_beta = append(list_x_beta, new(privacy.Scalar).Mul(x, beta))
   671  		list_xSquare = append(list_xSquare, new(privacy.Scalar).Mul(xSquare, alpha))
   672  		tmp := vectorMulScalar(powerVector(z, numValuePad), new(privacy.Scalar).Mul(zSquare, alpha))
   673  		list_zSquare = append(list_zSquare, tmp...)
   674  
   675  		list_V = append(list_V, cmsValue...)
   676  		list_t1 = append(list_t1, proof.t1)
   677  		list_t2 = append(list_t2, proof.t2)
   678  
   679  		// Verify the second argument
   680  		hashCache := x.ToBytesS()
   681  		L := proof.innerProductProof.l
   682  		R := proof.innerProductProof.r
   683  		s := make([]*privacy.Scalar, N)
   684  		sInverse := make([]*privacy.Scalar, N)
   685  		logN := int(math.Log2(float64(N)))
   686  		vSquareList := make([]*privacy.Scalar, logN)
   687  		vInverseSquareList := make([]*privacy.Scalar, logN)
   688  
   689  		for i := 0; i < N; i++ {
   690  			s[i] = new(privacy.Scalar).Set(proof.innerProductProof.a)
   691  			sInverse[i] = new(privacy.Scalar).Set(proof.innerProductProof.b)
   692  		}
   693  
   694  		for i := range L {
   695  			v := generateChallenge(hashCache, []*privacy.Point{L[i], R[i]})
   696  			hashCache = v.ToBytesS()
   697  			vInverse := new(privacy.Scalar).Invert(v)
   698  			vSquareList[i] = new(privacy.Scalar).Mul(v, v)
   699  			vInverseSquareList[i] = new(privacy.Scalar).Mul(vInverse, vInverse)
   700  
   701  			for j := 0; j < N; j++ {
   702  				if j&int(math.Pow(2, float64(logN-i-1))) != 0 {
   703  					s[j] = new(privacy.Scalar).Mul(s[j], v)
   704  					sInverse[j] = new(privacy.Scalar).Mul(sInverse[j], vInverse)
   705  				} else {
   706  					s[j] = new(privacy.Scalar).Mul(s[j], vInverse)
   707  					sInverse[j] = new(privacy.Scalar).Mul(sInverse[j], v)
   708  				}
   709  			}
   710  		}
   711  
   712  		lVector := make([]*privacy.Scalar, N)
   713  		rVector := make([]*privacy.Scalar, N)
   714  
   715  		vectorSum := make([]*privacy.Scalar, N)
   716  		zTmp := new(privacy.Scalar).Set(z)
   717  		for j := 0; j < numValuePad; j++ {
   718  			zTmp.Mul(zTmp, z)
   719  			for i := 0; i < maxExp; i++ {
   720  				vectorSum[j*maxExp+i] = new(privacy.Scalar).Mul(twoVectorN[i], zTmp)
   721  			}
   722  		}
   723  		yInverse := new(privacy.Scalar).Invert(y)
   724  		yTmp := new(privacy.Scalar).Set(y)
   725  		for j := 0; j < N; j++ {
   726  			yTmp.Mul(yTmp, yInverse)
   727  			lVector[j] = new(privacy.Scalar).Add(s[j], z)
   728  			rVector[j] = new(privacy.Scalar).Sub(sInverse[j], vectorSum[j])
   729  			rVector[j].Mul(rVector[j], yTmp)
   730  			rVector[j].Sub(rVector[j], z)
   731  
   732  			lVector[j].Mul(lVector[j], beta)
   733  			rVector[j].Mul(rVector[j], beta)
   734  		}
   735  
   736  		list_lVector = append(list_lVector, lVector...)
   737  		list_rVector = append(list_rVector, rVector...)
   738  
   739  		tmp1 := new(privacy.Point).MultiScalarMult(vSquareList, L)
   740  		tmp2 := new(privacy.Point).MultiScalarMult(vInverseSquareList, R)
   741  		list_LR = append(list_LR, new(privacy.Point).Add(tmp1, tmp2))
   742  
   743  		list_gVector = append(list_gVector, aggParam.g...)
   744  		list_hVector = append(list_hVector, aggParam.h...)
   745  
   746  		sum_mu.Add(sum_mu, new(privacy.Scalar).Mul(proof.mu, beta))
   747  		ab := new(privacy.Scalar).Mul(proof.innerProductProof.a, proof.innerProductProof.b)
   748  		absubthat := new(privacy.Scalar).Sub(ab, proof.tHat)
   749  		absubthat.Mul(absubthat, privacy.HashToScalar(x.ToBytesS()))
   750  		sum_absubthat.Add(sum_absubthat, new(privacy.Scalar).Mul(absubthat, beta))
   751  		list_A = append(list_A, proof.a)
   752  		list_S = append(list_S, proof.s)
   753  	}
   754  
   755  	tmp1 := new(privacy.Point).MultiScalarMult(list_lVector, list_gVector)
   756  	tmp2 := new(privacy.Point).MultiScalarMult(list_rVector, list_hVector)
   757  	tmp3 := new(privacy.Point).ScalarMult(AggParam.u, sum_absubthat)
   758  	tmp4 := new(privacy.Point).ScalarMult(baseH, sum_mu)
   759  	LHSPrime := new(privacy.Point).Add(tmp1, tmp2)
   760  	LHSPrime.Add(LHSPrime, tmp3)
   761  	LHSPrime.Add(LHSPrime, tmp4)
   762  
   763  	LHS := new(privacy.Point).AddPedersen(sum_tHat, baseG, sum_tauX, baseH)
   764  	LHSPrime.Add(LHSPrime, LHS)
   765  
   766  	tmp5 := new(privacy.Point).MultiScalarMult(list_beta, list_A)
   767  	tmp6 := new(privacy.Point).MultiScalarMult(list_x_beta, list_S)
   768  	RHSPrime := new(privacy.Point).Add(tmp5, tmp6)
   769  	RHSPrime.Add(RHSPrime, new(privacy.Point).MultiScalarMult(list_beta, list_LR))
   770  
   771  	part1 := new(privacy.Point).MultiScalarMult(list_x_alpha, list_t1)
   772  	part2 := new(privacy.Point).MultiScalarMult(list_xSquare, list_t2)
   773  	RHS := new(privacy.Point).Add(part1, part2)
   774  	RHS.Add(RHS, new(privacy.Point).MultiScalarMult(list_zSquare, list_V))
   775  	RHSPrime.Add(RHSPrime, RHS)
   776  	//fmt.Println("Batch Verification ", LHSPrime)
   777  	//fmt.Println("Batch Verification ", RHSPrime)
   778  
   779  	if !privacy.IsPointEqual(LHSPrime, RHSPrime) {
   780  		//privacy.Logger.Log.Errorf("batch verify aggregated range proof failed")
   781  		return false, errors.New("batch verify aggregated range proof failed"), -1
   782  	}
   783  	return true, nil, -1
   784  }
   785  
   786  // estimateMultiRangeProofSize estimate multi range proof size
   787  func EstimateMultiRangeProofSize(nOutput int) uint64 {
   788  	return uint64((nOutput+2*int(math.Log2(float64(privacy_util.MaxExp*roundUpPowTwo(nOutput))))+5)*privacy.Ed25519KeySize + 5*privacy.Ed25519KeySize + 2)
   789  }