github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/crypto/ringct/bulletproof_fast.go (about)

     1  // Copyright 2017-2018 DERO Project. All rights reserved.
     2  // Use of this source code in any form is governed by RESEARCH license.
     3  // license can be found in the LICENSE file.
     4  // GPG: 0F39 E425 8C65 3947 702A  8234 08B2 0360 A03A 9DE8
     5  //
     6  //
     7  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
     8  // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     9  // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
    10  // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    11  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    12  // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    13  // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
    14  // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
    15  // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    16  
    17  package ringct
    18  
    19  import "fmt"
    20  
    21  //import "math/big"
    22  //import "encoding/binary"
    23  import "sync"
    24  
    25  import "github.com/deroproject/derosuite/crypto"
    26  
    27  var HiS, GiS [maxN]crypto.SUPER_PRECOMPUTE_TABLE
    28  var once sync.Once
    29  
    30  // this should be called after Hi, Gi are setup
    31  func precompute_tables() {
    32  	fmt.Sprintf("junk")
    33  	for i := 0; i < maxN; i++ {
    34  		var tmp crypto.PRECOMPUTE_TABLE
    35  
    36  		crypto.GenPrecompute(&tmp, Hi[i])        // generate pre comp table
    37  		crypto.GenSuperPrecompute(&HiS[i], &tmp) // generate His precomp table
    38  
    39  		crypto.GenPrecompute(&tmp, Gi[i])        // generate pre comp table
    40  		crypto.GenSuperPrecompute(&GiS[i], &tmp) // generate His precomp table
    41  
    42  	}
    43  }
    44  
    45  // see the  references such as original paper and multiple implementations
    46  // https://eprint.iacr.org/2017/1066.pdf
    47  // https://blog.chain.com/faster-bulletproofs-with-ristretto-avx2-29450b4490cd
    48  
    49  func (proof *BulletProof) BULLETPROOF_Verify_fast() (result bool) {
    50  
    51  	defer func() { // safety so if anything wrong happens, verification fails
    52  		if r := recover(); r != nil {
    53  			result = false
    54  		}
    55  	}()
    56  
    57  	once.Do(precompute_tables) // generate pre compute tables
    58  
    59  	if !(len(proof.V) == 1) {
    60  		//V does not have exactly one element
    61  		return false
    62  	}
    63  
    64  	if len(proof.L) != len(proof.R) {
    65  		//Mismatched L and R sizes
    66  		return false
    67  	}
    68  	if len(proof.L) == 0 {
    69  		// Empty Proof
    70  		return false
    71  	}
    72  
    73  	if len(proof.L) != 6 {
    74  		//Proof is not for 64 bits
    75  		return false
    76  	}
    77  	
    78  	// these checks try to filter out rogue inputs
    79  	if proof.BULLETPROOF_BasicChecks() == false{
    80              return false
    81          }
    82      
    83  
    84  	logN := len(proof.L)
    85  	N := int(1 << uint(logN))
    86  
    87  	// reconstruct the challenges
    88  	hashcache := *(crypto.HashToScalar(proof.V[0][:]))  //rct::key hash_cache = rct::hash_to_scalar(proof.V[0]);
    89  	y := hash_cache_mash2(&hashcache, proof.A, proof.S) //  rct::key y = hash_cache_mash(hash_cache, proof.A, proof.S);
    90  
    91  	hashcache = *(crypto.HashToScalar(y[:])) // rct::key z = hash_cache = rct::hash_to_scalar(y);
    92  	z := hashcache
    93  	x := hash_cache_mash3(&hashcache, z, proof.T1, proof.T2) //rct::key x = hash_cache_mash(hash_cache, z, proof.T1, proof.T2);
    94  
    95  	x_ip := hash_cache_mash4(&hashcache, x, proof.taux, proof.mu, proof.t) //rct::key x_ip = hash_cache_mash(hash_cache, x, proof.taux, proof.mu, proof.t);
    96  
    97  	// PAPER LINE 61
    98  	//rct::key L61Left = rct::addKeys(rct::scalarmultBase(proof.taux), rct::scalarmultKey(rct::H, proof.t));
    99  	taux_base := crypto.ScalarmultBase(proof.taux)
   100  	L61Left := AddKeys_return(&taux_base, crypto.ScalarMultKey(&crypto.H, &proof.t))
   101  
   102  	k := crypto.Zero                 //rct::key k = rct::zero();
   103  	yN := vector_powers(y, int64(N)) //const auto yN = vector_powers(y, N);
   104  	ip1y := inner_product(oneN, yN)  //rct::key ip1y = inner_product(oneN, yN);
   105  	zsq := crypto.Zero               //rct::key zsq;
   106  	crypto.ScMul(&zsq, &z, &z)       //sc_mul(zsq.bytes, z.bytes, z.bytes);
   107  
   108  	var tmp, tmp2 crypto.Key             //rct::key tmp, tmp2;
   109  	crypto.ScMulSub(&k, &zsq, &ip1y, &k) //  sc_mulsub(k.bytes, zsq.bytes, ip1y.bytes, k.bytes);
   110  	var zcu crypto.Key                   //rct::key zcu;
   111  	crypto.ScMul(&zcu, &zsq, &z)         //sc_mul(zcu.bytes, zsq.bytes, z.bytes);
   112  	crypto.ScMulSub(&k, &zcu, &ip12, &k) //sc_mulsub(k.bytes, zcu.bytes, ip12.bytes, k.bytes);
   113  
   114  	crypto.ScMulAdd(&tmp, &z, &ip1y, &k)                 // sc_muladd(tmp.bytes, z.bytes, ip1y.bytes, k.bytes);
   115  	L61Right := *(crypto.ScalarMultKey(&crypto.H, &tmp)) //rct::key L61Right = rct::scalarmultKey(rct::H, tmp);
   116  
   117  	tmp = *(crypto.ScalarMultKey(&proof.V[0], &zsq)) //tmp = rct::scalarmultKey(proof.V[0], zsq);
   118  	crypto.AddKeys(&L61Right, &L61Right, &tmp)       //rct::addKeys(L61Right, L61Right, tmp);
   119  
   120  	tmp = *(crypto.ScalarMultKey(&proof.T1, &x)) // tmp = rct::scalarmultKey(proof.T1, x);
   121  	crypto.AddKeys(&L61Right, &L61Right, &tmp)   //ct::addKeys(L61Right, L61Right, tmp);
   122  
   123  	var xsq crypto.Key                             //rct::key xsq;
   124  	crypto.ScMul(&xsq, &x, &x)                     // sc_mul(xsq.bytes, x.bytes, x.bytes);
   125  	tmp = *(crypto.ScalarMultKey(&proof.T2, &xsq)) //tmp = rct::scalarmultKey(proof.T2, xsq);
   126  	crypto.AddKeys(&L61Right, &L61Right, &tmp)     //rct::addKeys(L61Right, L61Right, tmp);
   127  
   128  	if !(L61Right == L61Left) {
   129  		//MERROR("Verification failure at step 1");
   130  		// fmt.Printf("erification failure at step 1")
   131  		return false
   132  	}
   133  
   134  	//fmt.Printf("Verification passed at step 1")
   135  
   136  	// PAPER LINE 62
   137  	P := AddKeys_return(&proof.A, crypto.ScalarMultKey(&proof.S, &x)) //rct::key P = rct::addKeys(proof.A, rct::scalarmultKey(proof.S, x));
   138  
   139  	// Compute the number of rounds for the inner product
   140  	rounds := len(proof.L)
   141  
   142  	// PAPER LINES 21-22
   143  	// The inner product challenges are computed per round
   144  	w := make([]crypto.Key, rounds, rounds) //  rct::keyV w(rounds);
   145  	for i := 0; i < rounds; i++ {           ///for (size_t i = 0; i < rounds; ++i)
   146  		w[i] = hash_cache_mash2(&hashcache, proof.L[i], proof.R[i]) //w[i] = hash_cache_mash(hash_cache, proof.L[i], proof.R[i]);
   147  	}
   148  
   149  	// Basically PAPER LINES 24-25
   150  	// Compute the curvepoints from G[i] and H[i]
   151  	inner_prod := crypto.Identity // rct::key inner_prod = rct::identity();
   152  	yinvpow := crypto.Identity    // rct::key yinvpow = rct::identity();
   153  	ypow := crypto.Identity       // rct::key ypow = rct::identity();
   154  
   155  	yinv := invert_scalar(y)                   //const rct::key yinv = invert(y);
   156  	winv := make([]crypto.Key, rounds, rounds) //rct::keyV winv(rounds);
   157  	for i := 0; i < rounds; i++ {              //for (size_t i = 0; i < rounds; ++i)
   158  		winv[i] = invert_scalar(w[i]) //	winv[i] = invert(w[i]);
   159  	}
   160  
   161  	var intermediate_inner_prod crypto.ExtendedGroupElement
   162  	intermediate_inner_prod.Zero() // make identity
   163  
   164  	for i := 0; i < N; i++ { //for (size_t i = 0; i < N; ++i)
   165  
   166  		// Convert the index to binary IN REVERSE and construct the scalar exponent
   167  		g_scalar := proof.a                         //rct::key g_scalar = proof.a;
   168  		h_scalar := crypto.Zero                     // rct::key h_scalar;
   169  		crypto.ScMul(&h_scalar, &proof.b, &yinvpow) //sc_mul(h_scalar.bytes, proof.b.bytes, yinvpow.bytes);
   170  
   171  		// is this okay ???
   172  		for j := rounds; j > 0; { // for (size_t j = rounds; j-- > 0; )
   173  			j--
   174  			// FIXME below len can be ommitted and represents rounds
   175  			J := len(w) - j - 1 //size_t J = w.size() - j - 1;
   176  
   177  			if i&((1)<<uint(j)) == 0 { /////if ((i & (((size_t)1)<<j)) == 0)
   178  				crypto.ScMul(&g_scalar, &g_scalar, &winv[J]) //sc_mul(g_scalar.bytes, g_scalar.bytes, winv[J].bytes);
   179  				crypto.ScMul(&h_scalar, &h_scalar, &w[J])    // sc_mul(h_scalar.bytes, h_scalar.bytes, w[J].bytes);
   180  			} else {
   181  				crypto.ScMul(&g_scalar, &g_scalar, &w[J])    //sc_mul(g_scalar.bytes, g_scalar.bytes, w[J].bytes);
   182  				crypto.ScMul(&h_scalar, &h_scalar, &winv[J]) //sc_mul(h_scalar.bytes, h_scalar.bytes, winv[J].bytes);
   183  			}
   184  		}
   185  
   186  		// Adjust the scalars using the exponents from PAPER LINE 62
   187  		crypto.ScAdd(&g_scalar, &g_scalar, &z)                // sc_add(g_scalar.bytes, g_scalar.bytes, z.bytes);
   188  		crypto.ScMul(&tmp, &zsq, &twoN[i])                    //sc_mul(tmp.bytes, zsq.bytes, twoN[i].bytes);
   189  		crypto.ScMulAdd(&tmp, &z, &ypow, &tmp)                //sc_muladd(tmp.bytes, z.bytes, ypow.bytes, tmp.bytes);
   190  		crypto.ScMulSub(&h_scalar, &tmp, &yinvpow, &h_scalar) //  sc_mulsub(h_scalar.bytes, tmp.bytes, yinvpow.bytes, h_scalar.bytes);
   191  
   192  		// Now compute the basepoint's scalar multiplication
   193  		// Each of these could be written as a multiexp operation instead
   194  		// cross-check this line again
   195  		// TODO can be a major  performance improvement
   196  		// TODO maybe this can be used https://boringssl.googlesource.com/boringssl/+/2357/crypto/ec/wnaf.c
   197  		// https://github.com/bitcoin-core/secp256k1/blob/master/src/ecmult_impl.h
   198  		//crypto.AddKeys3_3(&tmp, &g_scalar, &Gi_Precomputed[i], &h_scalar, &Hi_Precomputed[i]) //rct::addKeys3(tmp, g_scalar, Gprecomp[i], h_scalar, Hprecomp[i]);
   199  		//crypto.AddKeys(&inner_prod, &inner_prod, &tmp)                                        //rct::addKeys(inner_prod, inner_prod, tmp);
   200  
   201  		var first, second, scratch crypto.ExtendedGroupElement
   202  		var cached crypto.CachedGroupElement
   203  		var c crypto.CompletedGroupElement
   204  		crypto.ScalarMultSuperPrecompute(&first, &g_scalar, &GiS[i])
   205  
   206  		crypto.ScalarMultSuperPrecompute(&second, &h_scalar, &HiS[i])
   207  
   208  		second.ToCached(&cached)
   209  		crypto.GeAdd(&c, &first, &cached) // add both points together
   210  
   211  		c.ToExtended(&scratch)
   212  		scratch.ToCached(&cached)
   213  		crypto.GeAdd(&c, &intermediate_inner_prod, &cached) //add with intermediate resule
   214  		c.ToExtended(&intermediate_inner_prod)
   215  
   216  		if i != N-1 {
   217  			crypto.ScMul(&yinvpow, &yinvpow, &yinv) //sc_mul(yinvpow.bytes, yinvpow.bytes, yinv.bytes);
   218  			crypto.ScMul(&ypow, &ypow, &y)          //sc_mul(ypow.bytes, ypow.bytes, y.bytes);
   219  		}
   220  	}
   221  
   222  	intermediate_inner_prod.ToBytes(&inner_prod)
   223  	//inner_prod = crypto.Multiscalarmult_compatibility(scalars,points)
   224  	//inner_prod = crypto.Multiscalarmult(scalars,points)
   225  
   226  	// fmt.Printf("inner prod fast %s\n",inner_prod)
   227  
   228  	// PAPER LINE 26
   229  	var pprime crypto.Key                       //rct::key pprime;
   230  	crypto.ScSub(&tmp, &crypto.Zero, &proof.mu) //sc_sub(tmp.bytes, rct::zero().bytes, proof.mu.bytes);
   231  
   232  	tmp_base := crypto.ScalarmultBase(tmp)
   233  	crypto.AddKeys(&pprime, &P, &tmp_base) //rct::addKeys(pprime, P, rct::scalarmultBase(tmp));
   234  
   235  	for i := 0; i < rounds; i++ { //for (size_t i = 0; i < rounds; ++i)
   236  
   237  		crypto.ScMul(&tmp, &w[i], &w[i])        //sc_mul(tmp.bytes, w[i].bytes, w[i].bytes);
   238  		crypto.ScMul(&tmp2, &winv[i], &winv[i]) //sc_mul(tmp2.bytes, winv[i].bytes, winv[i].bytes);
   239  		//#if 1
   240  		// ge_dsmp cacheL, cacheR;
   241  		// rct::precomp(cacheL, proof.L[i]);
   242  		//rct::precomp(cacheR, proof.R[i]);
   243  
   244  		ProofLi := new(crypto.ExtendedGroupElement)
   245  		ProofLi.FromBytes(&proof.L[i])
   246  
   247  		ProofRi := new(crypto.ExtendedGroupElement)
   248  		ProofRi.FromBytes(&proof.R[i])
   249  
   250  		var ProofLi_precomputed [8]crypto.CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A
   251  		crypto.GePrecompute(&ProofLi_precomputed, ProofLi)
   252  
   253  		var ProofRi_precomputed [8]crypto.CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A
   254  		crypto.GePrecompute(&ProofRi_precomputed, ProofRi)
   255  
   256  		// optimise these at the end only if possible
   257  		crypto.AddKeys3_3(&tmp, &tmp, &ProofLi_precomputed, &tmp2, &ProofRi_precomputed) //rct::addKeys3(tmp, tmp, cacheL, tmp2, cacheR);
   258  		crypto.AddKeys(&pprime, &pprime, &tmp)                                           //rct::addKeys(pprime, pprime, tmp);
   259  
   260  		//#endif
   261  	}
   262  
   263  	crypto.ScMul(&tmp, &proof.t, &x_ip)                                     // sc_mul(tmp.bytes, proof.t.bytes, x_ip.bytes);
   264  	crypto.AddKeys(&pprime, &pprime, crypto.ScalarMultKey(&crypto.H, &tmp)) //rct::addKeys(pprime, pprime, rct::scalarmultKey(rct::H, tmp));
   265  
   266  	crypto.ScMul(&tmp, &proof.a, &proof.b)         //  sc_mul(tmp.bytes, proof.a.bytes, proof.b.bytes);
   267  	crypto.ScMul(&tmp, &tmp, &x_ip)                // sc_mul(tmp.bytes, tmp.bytes, x_ip.bytes);
   268  	tmp = *(crypto.ScalarMultKey(&crypto.H, &tmp)) //tmp = rct::scalarmultKey(rct::H, tmp);
   269  	crypto.AddKeys(&tmp, &tmp, &inner_prod)        //rct::addKeys(tmp, tmp, inner_prod);
   270  
   271  	if !(pprime == tmp) {
   272  		// MERROR("Verification failure at step 2");
   273  		// fmt.Printf("Verification failure at step 2");
   274  		return false
   275  	}
   276  
   277  	//fmt.Printf("\n prime      %s\n tmp %s  bulletproof verified successfully\n", pprime, tmp)
   278  
   279  	return true
   280  }