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

     1  package bulletproofs
     2  
     3  import (
     4  	"errors"
     5  	"github.com/incognitochain/go-incognito-sdk/privacy"
     6  	"math"
     7  )
     8  
     9  type InnerProductWitness struct {
    10  	a []*privacy.Scalar
    11  	b []*privacy.Scalar
    12  	p *privacy.Point
    13  }
    14  
    15  type InnerProductProof struct {
    16  	l []*privacy.Point
    17  	r []*privacy.Point
    18  	a *privacy.Scalar
    19  	b *privacy.Scalar
    20  	p *privacy.Point
    21  }
    22  
    23  func (inner *InnerProductProof) Init() *InnerProductProof {
    24  	if inner == nil {
    25  		inner = new(InnerProductProof)
    26  	}
    27  	inner.l = []*privacy.Point{}
    28  	inner.r = []*privacy.Point{}
    29  	inner.a = new(privacy.Scalar)
    30  	inner.b = new(privacy.Scalar)
    31  	inner.p = new(privacy.Point).Identity()
    32  
    33  	return inner
    34  }
    35  
    36  func (proof InnerProductProof) ValidateSanity() bool {
    37  	if len(proof.l) != len(proof.r) {
    38  		return false
    39  	}
    40  	for i := 0; i < len(proof.l); i++ {
    41  		if !proof.l[i].PointValid() || !proof.r[i].PointValid() {
    42  			return false
    43  		}
    44  	}
    45  	if !proof.a.ScalarValid() || !proof.b.ScalarValid() {
    46  		return false
    47  	}
    48  	return proof.p.PointValid()
    49  }
    50  
    51  func (proof InnerProductProof) Bytes() []byte {
    52  	var res []byte
    53  
    54  	res = append(res, byte(len(proof.l)))
    55  	for _, l := range proof.l {
    56  		res = append(res, l.ToBytesS()...)
    57  	}
    58  
    59  	for _, r := range proof.r {
    60  		res = append(res, r.ToBytesS()...)
    61  	}
    62  
    63  	res = append(res, proof.a.ToBytesS()...)
    64  	res = append(res, proof.b.ToBytesS()...)
    65  	res = append(res, proof.p.ToBytesS()...)
    66  
    67  	return res
    68  }
    69  
    70  func (proof *InnerProductProof) SetBytes(bytes []byte) error {
    71  	if len(bytes) == 0 {
    72  		return nil
    73  	}
    74  
    75  	lenLArray := int(bytes[0])
    76  	offset := 1
    77  	var err error
    78  
    79  	proof.l = make([]*privacy.Point, lenLArray)
    80  	for i := 0; i < lenLArray; i++ {
    81  		if offset+privacy.Ed25519KeySize > len(bytes){
    82  			return errors.New("Inner Product Proof byte unmarshaling failed")
    83  		}
    84  		proof.l[i], err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
    85  		if err != nil {
    86  			return err
    87  		}
    88  		offset += privacy.Ed25519KeySize
    89  	}
    90  
    91  	proof.r = make([]*privacy.Point, lenLArray)
    92  	for i := 0; i < lenLArray; i++ {
    93  		if offset+privacy.Ed25519KeySize > len(bytes){
    94  			return errors.New("Inner Product Proof byte unmarshaling failed")
    95  		}
    96  		proof.r[i], err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
    97  		if err != nil {
    98  			return err
    99  		}
   100  		offset += privacy.Ed25519KeySize
   101  	}
   102  
   103  	if offset+privacy.Ed25519KeySize > len(bytes){
   104  		return errors.New("Inner Product Proof byte unmarshaling failed")
   105  	}
   106  	proof.a = new(privacy.Scalar).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   107  	offset += privacy.Ed25519KeySize
   108  
   109  	if offset+privacy.Ed25519KeySize > len(bytes){
   110  		return errors.New("Inner Product Proof byte unmarshaling failed")
   111  	}
   112  	proof.b = new(privacy.Scalar).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   113  	offset += privacy.Ed25519KeySize
   114  
   115  	if offset+privacy.Ed25519KeySize > len(bytes){
   116  		return errors.New("Inner Product Proof byte unmarshaling failed")
   117  	}
   118  	proof.p, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   119  	if err != nil {
   120  		return err
   121  	}
   122  
   123  	return nil
   124  }
   125  
   126  func (wit InnerProductWitness) Prove(GParam []*privacy.Point, HParam []*privacy.Point, uParam *privacy.Point, hashCache []byte) (*InnerProductProof, error) {
   127  	if len(wit.a) != len(wit.b) {
   128  		return nil, errors.New("invalid inputs")
   129  	}
   130  
   131  	N := len(wit.a)
   132  
   133  	a := make([]*privacy.Scalar, N)
   134  	b := make([]*privacy.Scalar, N)
   135  
   136  	for i := range wit.a {
   137  		a[i] = new(privacy.Scalar).Set(wit.a[i])
   138  		b[i] = new(privacy.Scalar).Set(wit.b[i])
   139  	}
   140  
   141  	p := new(privacy.Point).Set(wit.p)
   142  	G := make([]*privacy.Point, N)
   143  	H := make([]*privacy.Point, N)
   144  	for i := range G {
   145  		G[i] = new(privacy.Point).Set(GParam[i])
   146  		H[i] = new(privacy.Point).Set(HParam[i])
   147  	}
   148  
   149  	proof := new(InnerProductProof)
   150  	proof.l = make([]*privacy.Point, 0)
   151  	proof.r = make([]*privacy.Point, 0)
   152  	proof.p = new(privacy.Point).Set(wit.p)
   153  
   154  	for N > 1 {
   155  		nPrime := N / 2
   156  
   157  		cL, err := innerProduct(a[:nPrime], b[nPrime:])
   158  		if err != nil {
   159  			return nil, err
   160  		}
   161  		cR, err := innerProduct(a[nPrime:], b[:nPrime])
   162  		if err != nil {
   163  			return nil, err
   164  		}
   165  
   166  		L, err := encodeVectors(a[:nPrime], b[nPrime:], G[nPrime:], H[:nPrime])
   167  		if err != nil {
   168  			return nil, err
   169  		}
   170  		L.Add(L, new(privacy.Point).ScalarMult(uParam, cL))
   171  		proof.l = append(proof.l, L)
   172  
   173  		R, err := encodeVectors(a[nPrime:], b[:nPrime], G[:nPrime], H[nPrime:])
   174  		if err != nil {
   175  			return nil, err
   176  		}
   177  		R.Add(R, new(privacy.Point).ScalarMult(uParam, cR))
   178  		proof.r = append(proof.r, R)
   179  
   180  		x := generateChallenge(hashCache, []*privacy.Point{L, R})
   181  		hashCache = new(privacy.Scalar).Set(x).ToBytesS()
   182  
   183  		xInverse := new(privacy.Scalar).Invert(x)
   184  		xSquare := new(privacy.Scalar).Mul(x, x)
   185  		xSquareInverse := new(privacy.Scalar).Mul(xInverse, xInverse)
   186  
   187  		// calculate GPrime, HPrime, PPrime for the next loop
   188  		GPrime := make([]*privacy.Point, nPrime)
   189  		HPrime := make([]*privacy.Point, nPrime)
   190  
   191  		for i := range GPrime {
   192  			GPrime[i] = new(privacy.Point).AddPedersen(xInverse, G[i], x, G[i+nPrime])
   193  			HPrime[i] = new(privacy.Point).AddPedersen(x, H[i], xInverse, H[i+nPrime])
   194  		}
   195  
   196  		// x^2 * l + P + xInverse^2 * r
   197  		PPrime := new(privacy.Point).AddPedersen(xSquare, L, xSquareInverse, R)
   198  		PPrime.Add(PPrime, p)
   199  
   200  		// calculate aPrime, bPrime
   201  		aPrime := make([]*privacy.Scalar, nPrime)
   202  		bPrime := make([]*privacy.Scalar, nPrime)
   203  
   204  		for i := range aPrime {
   205  			aPrime[i] = new(privacy.Scalar).Mul(a[i], x)
   206  			aPrime[i] = new(privacy.Scalar).MulAdd(a[i+nPrime], xInverse, aPrime[i])
   207  
   208  			bPrime[i] = new(privacy.Scalar).Mul(b[i], xInverse)
   209  			bPrime[i] = new(privacy.Scalar).MulAdd(b[i+nPrime], x, bPrime[i])
   210  		}
   211  
   212  		a = aPrime
   213  		b = bPrime
   214  		p.Set(PPrime)
   215  		G = GPrime
   216  		H = HPrime
   217  		N = nPrime
   218  	}
   219  
   220  	proof.a = new(privacy.Scalar).Set(a[0])
   221  	proof.b = new(privacy.Scalar).Set(b[0])
   222  
   223  	return proof, nil
   224  }
   225  
   226  func (proof InnerProductProof) Verify(GParam []*privacy.Point, HParam []*privacy.Point, uParam *privacy.Point, hashCache []byte) bool {
   227  	//var aggParam = newBulletproofParams(1)
   228  	p := new(privacy.Point)
   229  	p.Set(proof.p)
   230  
   231  	n := len(GParam)
   232  	G := make([]*privacy.Point, n)
   233  	H := make([]*privacy.Point, n)
   234  	for i := range G {
   235  		G[i] = new(privacy.Point).Set(GParam[i])
   236  		H[i] = new(privacy.Point).Set(HParam[i])
   237  	}
   238  
   239  	for i := range proof.l {
   240  		nPrime := n / 2
   241  		x := generateChallenge(hashCache, []*privacy.Point{proof.l[i], proof.r[i]})
   242  		hashCache = new(privacy.Scalar).Set(x).ToBytesS()
   243  		xInverse := new(privacy.Scalar).Invert(x)
   244  		xSquare := new(privacy.Scalar).Mul(x, x)
   245  		xSquareInverse := new(privacy.Scalar).Mul(xInverse, xInverse)
   246  
   247  		// calculate GPrime, HPrime, PPrime for the next loop
   248  		GPrime := make([]*privacy.Point, nPrime)
   249  		HPrime := make([]*privacy.Point, nPrime)
   250  
   251  		for j := 0; j < len(GPrime); j++ {
   252  			GPrime[j] = new(privacy.Point).AddPedersen(xInverse, G[j], x, G[j+nPrime])
   253  			HPrime[j] = new(privacy.Point).AddPedersen(x, H[j], xInverse, H[j+nPrime])
   254  		}
   255  		// calculate x^2 * l + P + xInverse^2 * r
   256  		PPrime := new(privacy.Point).AddPedersen(xSquare, proof.l[i], xSquareInverse, proof.r[i])
   257  		PPrime.Add(PPrime, p)
   258  
   259  		p = PPrime
   260  		G = GPrime
   261  		H = HPrime
   262  		n = nPrime
   263  	}
   264  
   265  	c := new(privacy.Scalar).Mul(proof.a, proof.b)
   266  	rightPoint := new(privacy.Point).AddPedersen(proof.a, G[0], proof.b, H[0])
   267  	rightPoint.Add(rightPoint, new(privacy.Point).ScalarMult(uParam, c))
   268  	res := privacy.IsPointEqual(rightPoint, p)
   269  	if !res {
   270  		//Logger.Log.Error("Inner product argument failed:")
   271  		//Logger.Log.Error("p: %v\n", p)
   272  		//Logger.Log.Error("RightPoint: %v\n", rightPoint)
   273  	}
   274  
   275  	return res
   276  }
   277  
   278  func (proof InnerProductProof) VerifyFaster(GParam []*privacy.Point, HParam []*privacy.Point, uParam *privacy.Point, hashCache []byte) bool {
   279  	//var aggParam = newBulletproofParams(1)
   280  	p := new(privacy.Point)
   281  	p.Set(proof.p)
   282  	n := len(GParam)
   283  	G := make([]*privacy.Point, n)
   284  	H := make([]*privacy.Point, n)
   285  	s := make([]*privacy.Scalar, n)
   286  	sInverse := make([]*privacy.Scalar, n)
   287  
   288  	for i := range G {
   289  		G[i] = new(privacy.Point).Set(GParam[i])
   290  		H[i] = new(privacy.Point).Set(HParam[i])
   291  		s[i] = new(privacy.Scalar).FromUint64(1)
   292  		sInverse[i] = new(privacy.Scalar).FromUint64(1)
   293  	}
   294  	logN := int(math.Log2(float64(n)))
   295  	xList := make([]*privacy.Scalar, logN)
   296  	xInverseList := make([]*privacy.Scalar, logN)
   297  	xSquareList := make([]*privacy.Scalar, logN)
   298  	xInverseSquare_List := make([]*privacy.Scalar, logN)
   299  
   300  	//a*s ; b*s^-1
   301  
   302  	for i := range proof.l {
   303  		// calculate challenge x = hash(hash(G || H || u || p) || x || l || r)
   304  		xList[i] = generateChallenge(hashCache, []*privacy.Point{proof.l[i], proof.r[i]})
   305  		hashCache = new(privacy.Scalar).Set(xList[i]).ToBytesS()
   306  
   307  		xInverseList[i] = new(privacy.Scalar).Invert(xList[i])
   308  		xSquareList[i] = new(privacy.Scalar).Mul(xList[i], xList[i])
   309  		xInverseSquare_List[i] = new(privacy.Scalar).Mul(xInverseList[i], xInverseList[i])
   310  
   311  		//Update s, s^-1
   312  		for j := 0; j < n; j++ {
   313  			if j&int(math.Pow(2, float64(logN-i-1))) != 0 {
   314  				s[j] = new(privacy.Scalar).Mul(s[j], xList[i])
   315  				sInverse[j] = new(privacy.Scalar).Mul(sInverse[j], xInverseList[i])
   316  			} else {
   317  				s[j] = new(privacy.Scalar).Mul(s[j], xInverseList[i])
   318  				sInverse[j] = new(privacy.Scalar).Mul(sInverse[j], xList[i])
   319  			}
   320  		}
   321  	}
   322  
   323  	// Compute (g^s)^a (h^-s)^b u^(ab) = p l^(x^2) r^(-x^2)
   324  	c := new(privacy.Scalar).Mul(proof.a, proof.b)
   325  	rightHSPart1 := new(privacy.Point).MultiScalarMult(s, G)
   326  	rightHSPart1.ScalarMult(rightHSPart1, proof.a)
   327  	rightHSPart2 := new(privacy.Point).MultiScalarMult(sInverse, H)
   328  	rightHSPart2.ScalarMult(rightHSPart2, proof.b)
   329  
   330  	rightHS := new(privacy.Point).Add(rightHSPart1, rightHSPart2)
   331  	rightHS.Add(rightHS, new(privacy.Point).ScalarMult(uParam, c))
   332  
   333  	leftHSPart1 := new(privacy.Point).MultiScalarMult(xSquareList, proof.l)
   334  	leftHSPart2 := new(privacy.Point).MultiScalarMult(xInverseSquare_List, proof.r)
   335  
   336  	leftHS := new(privacy.Point).Add(leftHSPart1, leftHSPart2)
   337  	leftHS.Add(leftHS, proof.p)
   338  
   339  	res := privacy.IsPointEqual(rightHS, leftHS)
   340  	if !res {
   341  		//Logger.Log.Error("Inner product argument failed:")
   342  		//Logger.Log.Error("LHS: %v\n", leftHS)
   343  		//Logger.Log.Error("RHS: %v\n", rightHS)
   344  	}
   345  
   346  	return res
   347  }