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

     1  package aggregaterange
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/incognitochain/go-incognito-sdk/privacy"
     6  	"github.com/incognitochain/go-incognito-sdk/privacy/zkp/aggregaterange/bulletproofs"
     7  	"github.com/pkg/errors"
     8  )
     9  
    10  // This protocol proves in zero-knowledge that a list of committed values falls in [0, 2^64)
    11  
    12  type AggregatedRangeWitness struct {
    13  	values []uint64
    14  	rands  []*privacy.Scalar
    15  }
    16  
    17  type AggregatedRangeProof struct {
    18  	cmsValue          []*privacy.Point
    19  	a                 *privacy.Point
    20  	s                 *privacy.Point
    21  	t1                *privacy.Point
    22  	t2                *privacy.Point
    23  	tauX              *privacy.Scalar
    24  	tHat              *privacy.Scalar
    25  	mu                *privacy.Scalar
    26  	innerProductProof *InnerProductProof
    27  }
    28  
    29  func (proof AggregatedRangeProof) GetCmValues() []*privacy.Point {
    30  	return proof.cmsValue
    31  }
    32  
    33  func (proof AggregatedRangeProof) ValidateSanity() bool {
    34  	for i := 0; i < len(proof.cmsValue); i++ {
    35  		if !proof.cmsValue[i].PointValid() {
    36  			return false
    37  		}
    38  	}
    39  	if !proof.a.PointValid() {
    40  		return false
    41  	}
    42  	if !proof.s.PointValid() {
    43  		return false
    44  	}
    45  	if !proof.t1.PointValid() {
    46  		return false
    47  	}
    48  	if !proof.t2.PointValid() {
    49  		return false
    50  	}
    51  	if !proof.tauX.ScalarValid() {
    52  		return false
    53  	}
    54  	if !proof.tHat.ScalarValid() {
    55  		return false
    56  	}
    57  	if !proof.mu.ScalarValid() {
    58  		return false
    59  	}
    60  
    61  	return proof.innerProductProof.ValidateSanity()
    62  }
    63  
    64  func (proof *AggregatedRangeProof) Init() {
    65  	proof.a = new(privacy.Point).Identity()
    66  	proof.s = new(privacy.Point).Identity()
    67  	proof.t1 = new(privacy.Point).Identity()
    68  	proof.t2 = new(privacy.Point).Identity()
    69  	proof.tauX = new(privacy.Scalar)
    70  	proof.tHat = new(privacy.Scalar)
    71  	proof.mu = new(privacy.Scalar)
    72  	proof.innerProductProof = new(InnerProductProof)
    73  }
    74  
    75  func (proof AggregatedRangeProof) IsNil() bool {
    76  	if proof.a == nil {
    77  		return true
    78  	}
    79  	if proof.s == nil {
    80  		return true
    81  	}
    82  	if proof.t1 == nil {
    83  		return true
    84  	}
    85  	if proof.t2 == nil {
    86  		return true
    87  	}
    88  	if proof.tauX == nil {
    89  		return true
    90  	}
    91  	if proof.tHat == nil {
    92  		return true
    93  	}
    94  	if proof.mu == nil {
    95  		return true
    96  	}
    97  	return proof.innerProductProof == nil
    98  }
    99  
   100  func (proof AggregatedRangeProof) Bytes() []byte {
   101  	var res []byte
   102  
   103  	if proof.IsNil() {
   104  		return []byte{}
   105  	}
   106  
   107  	res = append(res, byte(len(proof.cmsValue)))
   108  	for i := 0; i < len(proof.cmsValue); i++ {
   109  		res = append(res, proof.cmsValue[i].ToBytesS()...)
   110  	}
   111  
   112  	res = append(res, proof.a.ToBytesS()...)
   113  	res = append(res, proof.s.ToBytesS()...)
   114  	res = append(res, proof.t1.ToBytesS()...)
   115  	res = append(res, proof.t2.ToBytesS()...)
   116  
   117  	res = append(res, proof.tauX.ToBytesS()...)
   118  	res = append(res, proof.tHat.ToBytesS()...)
   119  	res = append(res, proof.mu.ToBytesS()...)
   120  	res = append(res, proof.innerProductProof.Bytes()...)
   121  
   122  	return res
   123  
   124  }
   125  
   126  func (proof *AggregatedRangeProof) SetBytes(bytes []byte) error {
   127  	if len(bytes) == 0 {
   128  		return nil
   129  	}
   130  
   131  	lenValues := int(bytes[0])
   132  	offset := 1
   133  	var err error
   134  
   135  	proof.cmsValue = make([]*privacy.Point, lenValues)
   136  	for i := 0; i < lenValues; i++ {
   137  		proof.cmsValue[i], err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   138  		if err != nil {
   139  			return err
   140  		}
   141  		offset += privacy.Ed25519KeySize
   142  	}
   143  
   144  	proof.a, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   145  	if err != nil {
   146  		return err
   147  	}
   148  	offset += privacy.Ed25519KeySize
   149  
   150  	proof.s, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   151  	if err != nil {
   152  		return err
   153  	}
   154  	offset += privacy.Ed25519KeySize
   155  
   156  	proof.t1, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   157  	if err != nil {
   158  		return err
   159  	}
   160  	offset += privacy.Ed25519KeySize
   161  
   162  	proof.t2, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   163  	if err != nil {
   164  		return err
   165  	}
   166  	offset += privacy.Ed25519KeySize
   167  
   168  	proof.tauX = new(privacy.Scalar).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   169  	offset += privacy.Ed25519KeySize
   170  
   171  	proof.tHat = new(privacy.Scalar).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   172  	offset += privacy.Ed25519KeySize
   173  
   174  	proof.mu = new(privacy.Scalar).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   175  	offset += privacy.Ed25519KeySize
   176  
   177  	proof.innerProductProof = new(InnerProductProof)
   178  	proof.innerProductProof.SetBytes(bytes[offset:])
   179  
   180  	return nil
   181  }
   182  
   183  func (wit *AggregatedRangeWitness) Set(values []uint64, rands []*privacy.Scalar) {
   184  	numValue := len(values)
   185  	wit.values = make([]uint64, numValue)
   186  	wit.rands = make([]*privacy.Scalar, numValue)
   187  
   188  	for i := range values {
   189  		wit.values[i] = values[i]
   190  		wit.rands[i] = new(privacy.Scalar).Set(rands[i])
   191  	}
   192  }
   193  
   194  func (wit AggregatedRangeWitness) Prove() (*AggregatedRangeProof, error) {
   195  	wit2 := new(bulletproofs.AggregatedRangeWitness)
   196  	wit2.Set(wit.values, wit.rands)
   197  
   198  	proof2, err := wit2.Prove()
   199  	if err != nil {
   200  		return nil, errors.New(fmt.Sprintf("cannot prove bulletproof v2. Error %v", err))
   201  	}
   202  	proof2Bytes := proof2.Bytes()
   203  	proof := new(AggregatedRangeProof)
   204  	err = proof.SetBytes(proof2Bytes)
   205  	if err != nil {
   206  		fmt.Println("Error:", err)
   207  		return nil, errors.New(fmt.Sprintf("cannot convert proof ver 2  to ver 1. Error %v", err))
   208  	}
   209  	return proof, nil
   210  }
   211  
   212  func (proof AggregatedRangeProof) Verify() (bool, error) {
   213  	numValue := len(proof.cmsValue)
   214  	if numValue > maxOutputNumber {
   215  		return false, errors.New("Must less than maxOutputNumber")
   216  	}
   217  	numValuePad := pad(numValue)
   218  	aggParam := new(bulletproofParams)
   219  	aggParam.g = AggParam.g[0 : numValuePad*maxExp]
   220  	aggParam.h = AggParam.h[0 : numValuePad*maxExp]
   221  	aggParam.u = AggParam.u
   222  	csByteH := []byte{}
   223  	csByteG := []byte{}
   224  	for i := 0; i < len(aggParam.g); i++ {
   225  		csByteG = append(csByteG, aggParam.g[i].ToBytesS()...)
   226  		csByteH = append(csByteH, aggParam.h[i].ToBytesS()...)
   227  	}
   228  	aggParam.cs = append(aggParam.cs, csByteG...)
   229  	aggParam.cs = append(aggParam.cs, csByteH...)
   230  	aggParam.cs = append(aggParam.cs, aggParam.u.ToBytesS()...)
   231  
   232  	tmpcmsValue := proof.cmsValue
   233  
   234  	for i := numValue; i < numValuePad; i++ {
   235  		identity := new(privacy.Point).Identity()
   236  		tmpcmsValue = append(tmpcmsValue, identity)
   237  	}
   238  
   239  	n := maxExp
   240  	oneNumber := new(privacy.Scalar).FromUint64(1)
   241  	twoNumber := new(privacy.Scalar).FromUint64(2)
   242  	oneVector := powerVector(oneNumber, n*numValuePad)
   243  	oneVectorN := powerVector(oneNumber, n)
   244  	twoVectorN := powerVector(twoNumber, n)
   245  
   246  	// recalculate challenge y, z
   247  	y := generateChallenge([][]byte{aggParam.cs, proof.a.ToBytesS(), proof.s.ToBytesS()})
   248  	z := generateChallenge([][]byte{aggParam.cs, proof.a.ToBytesS(), proof.s.ToBytesS(), y.ToBytesS()})
   249  	zSquare := new(privacy.Scalar).Mul(z, z)
   250  
   251  	// challenge x = hash(G || H || A || S || T1 || T2)
   252  	//fmt.Printf("T2: %v\n", proof.t2)
   253  	x := generateChallenge([][]byte{aggParam.cs, proof.a.ToBytesS(), proof.s.ToBytesS(), proof.t1.ToBytesS(), proof.t2.ToBytesS()})
   254  	xSquare := new(privacy.Scalar).Mul(x, x)
   255  
   256  	yVector := powerVector(y, n*numValuePad)
   257  	// HPrime = H^(y^(1-i)
   258  	HPrime := make([]*privacy.Point, n*numValuePad)
   259  	yInverse := new(privacy.Scalar).Invert(y)
   260  	expyInverse := new(privacy.Scalar).FromUint64(1)
   261  	for i := 0; i < n*numValuePad; i++ {
   262  		HPrime[i] = new(privacy.Point).ScalarMult(aggParam.h[i], expyInverse)
   263  		expyInverse.Mul(expyInverse, yInverse)
   264  	}
   265  
   266  	// g^tHat * h^tauX = V^(z^2) * g^delta(y,z) * T1^x * T2^(x^2)
   267  	deltaYZ := new(privacy.Scalar).Sub(z, zSquare)
   268  
   269  	// innerProduct1 = <1^(n*m), y^(n*m)>
   270  	innerProduct1, err := innerProduct(oneVector, yVector)
   271  	if err != nil {
   272  		return false, privacy.NewPrivacyErr(privacy.CalInnerProductErr, err)
   273  	}
   274  
   275  	deltaYZ.Mul(deltaYZ, innerProduct1)
   276  
   277  	// innerProduct2 = <1^n, 2^n>
   278  	innerProduct2, err := innerProduct(oneVectorN, twoVectorN)
   279  	if err != nil {
   280  		return false, privacy.NewPrivacyErr(privacy.CalInnerProductErr, err)
   281  	}
   282  
   283  	sum := new(privacy.Scalar).FromUint64(0)
   284  	zTmp := new(privacy.Scalar).Set(zSquare)
   285  	for j := 0; j < numValuePad; j++ {
   286  		zTmp.Mul(zTmp, z)
   287  		sum.Add(sum, zTmp)
   288  	}
   289  	sum.Mul(sum, innerProduct2)
   290  	deltaYZ.Sub(deltaYZ, sum)
   291  
   292  	left1 := privacy.PedCom.CommitAtIndex(proof.tHat, proof.tauX, privacy.PedersenValueIndex)
   293  
   294  	right1 := new(privacy.Point).ScalarMult(proof.t2, xSquare)
   295  	right1.Add(right1, new(privacy.Point).AddPedersen(deltaYZ, privacy.PedCom.G[privacy.PedersenValueIndex], x, proof.t1))
   296  
   297  	expVector := vectorMulScalar(powerVector(z, numValuePad), zSquare)
   298  	right1.Add(right1, new(privacy.Point).MultiScalarMult(expVector, tmpcmsValue))
   299  
   300  	if !privacy.IsPointEqual(left1, right1) {
   301  		return false, errors.New("verify aggregated range proof statement 1 failed")
   302  	}
   303  
   304  	innerProductArgValid := proof.innerProductProof.Verify(aggParam)
   305  	if !innerProductArgValid {
   306  		return false, errors.New("verify aggregated range proof statement 2 failed")
   307  	}
   308  
   309  	return true, nil
   310  }
   311  
   312  func VerifyBatchingAggregatedRangeProofs(proofs []*AggregatedRangeProof) (bool, error, int) {
   313  	innerProductProofs := make([]*InnerProductProof, 0)
   314  	csList := make([][]byte, 0)
   315  	for k, proof := range proofs {
   316  		numValue := len(proof.cmsValue)
   317  		if numValue > maxOutputNumber {
   318  			return false, errors.New("Must less than maxOutputNumber"), k
   319  		}
   320  		numValuePad := pad(numValue)
   321  		aggParam := new(bulletproofParams)
   322  		aggParam.g = AggParam.g[0 : numValuePad*maxExp]
   323  		aggParam.h = AggParam.h[0 : numValuePad*maxExp]
   324  		aggParam.u = AggParam.u
   325  		csByteH := []byte{}
   326  		csByteG := []byte{}
   327  		for i := 0; i < len(aggParam.g); i++ {
   328  			csByteG = append(csByteG, aggParam.g[i].ToBytesS()...)
   329  			csByteH = append(csByteH, aggParam.h[i].ToBytesS()...)
   330  		}
   331  		aggParam.cs = append(aggParam.cs, csByteG...)
   332  		aggParam.cs = append(aggParam.cs, csByteH...)
   333  		aggParam.cs = append(aggParam.cs, aggParam.u.ToBytesS()...)
   334  
   335  		tmpcmsValue := proof.cmsValue
   336  
   337  		for i := numValue; i < numValuePad; i++ {
   338  			identity := new(privacy.Point).Identity()
   339  			tmpcmsValue = append(tmpcmsValue, identity)
   340  		}
   341  
   342  		n := maxExp
   343  		oneNumber := new(privacy.Scalar).FromUint64(1)
   344  		twoNumber := new(privacy.Scalar).FromUint64(2)
   345  		oneVector := powerVector(oneNumber, n*numValuePad)
   346  		oneVectorN := powerVector(oneNumber, n)
   347  		twoVectorN := powerVector(twoNumber, n)
   348  
   349  		// recalculate challenge y, z
   350  		y := generateChallenge([][]byte{aggParam.cs, proof.a.ToBytesS(), proof.s.ToBytesS()})
   351  		z := generateChallenge([][]byte{aggParam.cs, proof.a.ToBytesS(), proof.s.ToBytesS(), y.ToBytesS()})
   352  		zSquare := new(privacy.Scalar).Mul(z, z)
   353  
   354  		// challenge x = hash(G || H || A || S || T1 || T2)
   355  		//fmt.Printf("T2: %v\n", proof.t2)
   356  		x := generateChallenge([][]byte{aggParam.cs, proof.a.ToBytesS(), proof.s.ToBytesS(), proof.t1.ToBytesS(), proof.t2.ToBytesS()})
   357  		xSquare := new(privacy.Scalar).Mul(x, x)
   358  
   359  		yVector := powerVector(y, n*numValuePad)
   360  		// HPrime = H^(y^(1-i)
   361  		HPrime := make([]*privacy.Point, n*numValuePad)
   362  		yInverse := new(privacy.Scalar).Invert(y)
   363  		expyInverse := new(privacy.Scalar).FromUint64(1)
   364  		for i := 0; i < n*numValuePad; i++ {
   365  			HPrime[i] = new(privacy.Point).ScalarMult(aggParam.h[i], expyInverse)
   366  			expyInverse.Mul(expyInverse, yInverse)
   367  		}
   368  
   369  		// g^tHat * h^tauX = V^(z^2) * g^delta(y,z) * T1^x * T2^(x^2)
   370  		deltaYZ := new(privacy.Scalar).Sub(z, zSquare)
   371  
   372  		// innerProduct1 = <1^(n*m), y^(n*m)>
   373  		innerProduct1, err := innerProduct(oneVector, yVector)
   374  		if err != nil {
   375  			return false, privacy.NewPrivacyErr(privacy.CalInnerProductErr, err), k
   376  		}
   377  
   378  		deltaYZ.Mul(deltaYZ, innerProduct1)
   379  
   380  		// innerProduct2 = <1^n, 2^n>
   381  		innerProduct2, err := innerProduct(oneVectorN, twoVectorN)
   382  		if err != nil {
   383  			return false, privacy.NewPrivacyErr(privacy.CalInnerProductErr, err), k
   384  		}
   385  
   386  		sum := new(privacy.Scalar).FromUint64(0)
   387  		zTmp := new(privacy.Scalar).Set(zSquare)
   388  		for j := 0; j < numValuePad; j++ {
   389  			zTmp.Mul(zTmp, z)
   390  			sum.Add(sum, zTmp)
   391  		}
   392  		sum.Mul(sum, innerProduct2)
   393  		deltaYZ.Sub(deltaYZ, sum)
   394  
   395  		left1 := privacy.PedCom.CommitAtIndex(proof.tHat, proof.tauX, privacy.PedersenValueIndex)
   396  
   397  		right1 := new(privacy.Point).ScalarMult(proof.t2, xSquare)
   398  		right1.Add(right1, new(privacy.Point).AddPedersen(deltaYZ, privacy.PedCom.G[privacy.PedersenValueIndex], x, proof.t1))
   399  
   400  		expVector := vectorMulScalar(powerVector(z, numValuePad), zSquare)
   401  		right1.Add(right1, new(privacy.Point).MultiScalarMult(expVector, tmpcmsValue))
   402  
   403  		if !privacy.IsPointEqual(left1, right1) {
   404  			return false, fmt.Errorf("verify aggregated range proof statement 1 failed index %d", k), k
   405  		}
   406  
   407  		innerProductProofs = append(innerProductProofs, proof.innerProductProof)
   408  		csList = append(csList, aggParam.cs)
   409  	}
   410  
   411  	innerProductArgsValid := VerifyBatchingInnerProductProofs(innerProductProofs, csList)
   412  	if !innerProductArgsValid {
   413  		return false, errors.New("verify batch aggregated range proofs statement 2 failed"), -1
   414  	}
   415  
   416  	return true, nil, -1
   417  }