github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/crypto/ringct/bulletproof_ultrafast.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 Gi_Hi [maxN]crypto.PRECOMPUTE_TABLE
    28  var ultraonce sync.Once
    29  
    30  // this should be called after Hi, Gi are setup
    31  func precompute_tables_ultra() {
    32  	fmt.Sprintf("junk")
    33  	for i := 0; i < maxN; i++ {
    34  		// fmt.Printf("genrating  %d \n",i)
    35  		crypto.GenDoublePrecompute(&Gi_Hi[i], Gi[i], Hi[i]) // generate double precompute tables
    36  	}
    37  }
    38  
    39  // see the  references such as original paper and multiple implementations
    40  // https://eprint.iacr.org/2017/1066.pdf
    41  // https://blog.chain.com/faster-bulletproofs-with-ristretto-avx2-29450b4490cd
    42  
    43  func (proof *BulletProof) BULLETPROOF_Verify_ultrafast() (result bool) {
    44  
    45  	defer func() { // safety so if anything wrong happens, verification fails
    46  		if r := recover(); r != nil {
    47  			result = false
    48  		}
    49  	}()
    50  
    51  	ultraonce.Do(precompute_tables_ultra) // generate pre compute tables
    52  
    53  	if !(len(proof.V) == 1) {
    54  		//V does not have exactly one element
    55  		return false
    56  	}
    57  
    58  	if len(proof.L) != len(proof.R) {
    59  		//Mismatched L and R sizes
    60  		return false
    61  	}
    62  	if len(proof.L) == 0 {
    63  		// Empty Proof
    64  		return false
    65  	}
    66  
    67  	if len(proof.L) != 6 {
    68  		//Proof is not for 64 bits
    69  		return false
    70  	}
    71  
    72  	// these checks try to filter out rogue inputs
    73  	if proof.BULLETPROOF_BasicChecks() == false{
    74              return false
    75          }
    76      
    77  
    78  	logN := len(proof.L)
    79  	N := int(1 << uint(logN))
    80  
    81  	// reconstruct the challenges
    82  	hashcache := *(crypto.HashToScalar(proof.V[0][:]))  //rct::key hash_cache = rct::hash_to_scalar(proof.V[0]);
    83  	y := hash_cache_mash2(&hashcache, proof.A, proof.S) //  rct::key y = hash_cache_mash(hash_cache, proof.A, proof.S);
    84  
    85  	hashcache = *(crypto.HashToScalar(y[:])) // rct::key z = hash_cache = rct::hash_to_scalar(y);
    86  	z := hashcache
    87  	x := hash_cache_mash3(&hashcache, z, proof.T1, proof.T2) //rct::key x = hash_cache_mash(hash_cache, z, proof.T1, proof.T2);
    88  
    89  	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);
    90  
    91  	// PAPER LINE 61
    92  	//rct::key L61Left = rct::addKeys(rct::scalarmultBase(proof.taux), rct::scalarmultKey(rct::H, proof.t));
    93  	taux_base := crypto.ScalarmultBase(proof.taux)
    94  	L61Left := AddKeys_return(&taux_base, crypto.ScalarMultKey(&crypto.H, &proof.t))
    95  
    96  	k := crypto.Zero                 //rct::key k = rct::zero();
    97  	yN := vector_powers(y, int64(N)) //const auto yN = vector_powers(y, N);
    98  	ip1y := inner_product(oneN, yN)  //rct::key ip1y = inner_product(oneN, yN);
    99  	zsq := crypto.Zero               //rct::key zsq;
   100  	crypto.ScMul(&zsq, &z, &z)       //sc_mul(zsq.bytes, z.bytes, z.bytes);
   101  
   102  	var tmp, tmp2 crypto.Key             //rct::key tmp, tmp2;
   103  	crypto.ScMulSub(&k, &zsq, &ip1y, &k) //  sc_mulsub(k.bytes, zsq.bytes, ip1y.bytes, k.bytes);
   104  	var zcu crypto.Key                   //rct::key zcu;
   105  	crypto.ScMul(&zcu, &zsq, &z)         //sc_mul(zcu.bytes, zsq.bytes, z.bytes);
   106  	crypto.ScMulSub(&k, &zcu, &ip12, &k) //sc_mulsub(k.bytes, zcu.bytes, ip12.bytes, k.bytes);
   107  
   108  	crypto.ScMulAdd(&tmp, &z, &ip1y, &k)                 // sc_muladd(tmp.bytes, z.bytes, ip1y.bytes, k.bytes);
   109  	L61Right := *(crypto.ScalarMultKey(&crypto.H, &tmp)) //rct::key L61Right = rct::scalarmultKey(rct::H, tmp);
   110  
   111  	tmp = *(crypto.ScalarMultKey(&proof.V[0], &zsq)) //tmp = rct::scalarmultKey(proof.V[0], zsq);
   112  	crypto.AddKeys(&L61Right, &L61Right, &tmp)       //rct::addKeys(L61Right, L61Right, tmp);
   113  
   114  	tmp = *(crypto.ScalarMultKey(&proof.T1, &x)) // tmp = rct::scalarmultKey(proof.T1, x);
   115  	crypto.AddKeys(&L61Right, &L61Right, &tmp)   //ct::addKeys(L61Right, L61Right, tmp);
   116  
   117  	var xsq crypto.Key                             //rct::key xsq;
   118  	crypto.ScMul(&xsq, &x, &x)                     // sc_mul(xsq.bytes, x.bytes, x.bytes);
   119  	tmp = *(crypto.ScalarMultKey(&proof.T2, &xsq)) //tmp = rct::scalarmultKey(proof.T2, xsq);
   120  	crypto.AddKeys(&L61Right, &L61Right, &tmp)     //rct::addKeys(L61Right, L61Right, tmp);
   121  
   122  	if !(L61Right == L61Left) {
   123  		//MERROR("Verification failure at step 1");
   124  		// fmt.Printf("erification failure at step 1")
   125  		return false
   126  	}
   127  
   128  	//fmt.Printf("Verification passed at step 1")
   129  
   130  	// PAPER LINE 62
   131  	P := AddKeys_return(&proof.A, crypto.ScalarMultKey(&proof.S, &x)) //rct::key P = rct::addKeys(proof.A, rct::scalarmultKey(proof.S, x));
   132  
   133  	// Compute the number of rounds for the inner product
   134  	rounds := len(proof.L)
   135  
   136  	// PAPER LINES 21-22
   137  	// The inner product challenges are computed per round
   138  	w := make([]crypto.Key, rounds, rounds) //  rct::keyV w(rounds);
   139  	for i := 0; i < rounds; i++ {           ///for (size_t i = 0; i < rounds; ++i)
   140  		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]);
   141  	}
   142  
   143  	// Basically PAPER LINES 24-25
   144  	// Compute the curvepoints from G[i] and H[i]
   145  	inner_prod := crypto.Identity // rct::key inner_prod = rct::identity();
   146  	yinvpow := crypto.Identity    // rct::key yinvpow = rct::identity();
   147  	ypow := crypto.Identity       // rct::key ypow = rct::identity();
   148  
   149  	yinv := invert_scalar(y)                   //const rct::key yinv = invert(y);
   150  	winv := make([]crypto.Key, rounds, rounds) //rct::keyV winv(rounds);
   151  	for i := 0; i < rounds; i++ {              //for (size_t i = 0; i < rounds; ++i)
   152  		winv[i] = invert_scalar(w[i]) //	winv[i] = invert(w[i]);
   153  	}
   154  
   155  	var s1, s2 [maxN]crypto.Key // collect scalars for deferred computation
   156  
   157  	for i := 0; i < N; i++ { //for (size_t i = 0; i < N; ++i)
   158  
   159  		// Convert the index to binary IN REVERSE and construct the scalar exponent
   160  		g_scalar := proof.a                         //rct::key g_scalar = proof.a;
   161  		h_scalar := crypto.Zero                     // rct::key h_scalar;
   162  		crypto.ScMul(&h_scalar, &proof.b, &yinvpow) //sc_mul(h_scalar.bytes, proof.b.bytes, yinvpow.bytes);
   163  
   164  		// is this okay ???
   165  		for j := rounds; j > 0; { // for (size_t j = rounds; j-- > 0; )
   166  			j--
   167  			// FIXME below len can be ommitted and represents rounds
   168  			J := len(w) - j - 1 //size_t J = w.size() - j - 1;
   169  
   170  			if i&((1)<<uint(j)) == 0 { /////if ((i & (((size_t)1)<<j)) == 0)
   171  				crypto.ScMul(&g_scalar, &g_scalar, &winv[J]) //sc_mul(g_scalar.bytes, g_scalar.bytes, winv[J].bytes);
   172  				crypto.ScMul(&h_scalar, &h_scalar, &w[J])    // sc_mul(h_scalar.bytes, h_scalar.bytes, w[J].bytes);
   173  			} else {
   174  				crypto.ScMul(&g_scalar, &g_scalar, &w[J])    //sc_mul(g_scalar.bytes, g_scalar.bytes, w[J].bytes);
   175  				crypto.ScMul(&h_scalar, &h_scalar, &winv[J]) //sc_mul(h_scalar.bytes, h_scalar.bytes, winv[J].bytes);
   176  			}
   177  		}
   178  
   179  		// Adjust the scalars using the exponents from PAPER LINE 62
   180  		crypto.ScAdd(&g_scalar, &g_scalar, &z)                // sc_add(g_scalar.bytes, g_scalar.bytes, z.bytes);
   181  		crypto.ScMul(&tmp, &zsq, &twoN[i])                    //sc_mul(tmp.bytes, zsq.bytes, twoN[i].bytes);
   182  		crypto.ScMulAdd(&tmp, &z, &ypow, &tmp)                //sc_muladd(tmp.bytes, z.bytes, ypow.bytes, tmp.bytes);
   183  		crypto.ScMulSub(&h_scalar, &tmp, &yinvpow, &h_scalar) //  sc_mulsub(h_scalar.bytes, tmp.bytes, yinvpow.bytes, h_scalar.bytes);
   184  
   185  		// Now compute the basepoint's scalar multiplication
   186  		// Each of these could be written as a multiexp operation instead
   187  		// cross-check this line again
   188  		// TODO can be a major  performance improvement
   189  		// TODO maybe this can be used https://boringssl.googlesource.com/boringssl/+/2357/crypto/ec/wnaf.c
   190  		// https://github.com/bitcoin-core/secp256k1/blob/master/src/ecmult_impl.h
   191  		//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]);
   192  		//crypto.AddKeys(&inner_prod, &inner_prod, &tmp)                                        //rct::addKeys(inner_prod, inner_prod, tmp);
   193  
   194  		s1[i] = g_scalar
   195  		s2[i] = h_scalar
   196  
   197  		if i != N-1 {
   198  			crypto.ScMul(&yinvpow, &yinvpow, &yinv) //sc_mul(yinvpow.bytes, yinvpow.bytes, yinv.bytes);
   199  			crypto.ScMul(&ypow, &ypow, &y)          //sc_mul(ypow.bytes, ypow.bytes, y.bytes);
   200  		}
   201  	}
   202  
   203  	var intermediate_inner_prod crypto.ExtendedGroupElement
   204  	crypto.DoubleScalarDoubleBaseMulPrecomputed64(&intermediate_inner_prod, s1[:], s2[:], Gi_Hi[:])
   205  	intermediate_inner_prod.ToBytes(&inner_prod)
   206  	//inner_prod = crypto.Multiscalarmult_compatibility(scalars,points)
   207  	//inner_prod = crypto.Multiscalarmult(scalars,points)
   208  
   209  	//fmt.Printf("inner prod ultra fast %s \n",inner_prod)
   210  
   211  	// PAPER LINE 26
   212  	var pprime crypto.Key                       //rct::key pprime;
   213  	crypto.ScSub(&tmp, &crypto.Zero, &proof.mu) //sc_sub(tmp.bytes, rct::zero().bytes, proof.mu.bytes);
   214  
   215  	tmp_base := crypto.ScalarmultBase(tmp)
   216  	crypto.AddKeys(&pprime, &P, &tmp_base) //rct::addKeys(pprime, P, rct::scalarmultBase(tmp));
   217  
   218  	for i := 0; i < rounds; i++ { //for (size_t i = 0; i < rounds; ++i)
   219  
   220  		crypto.ScMul(&tmp, &w[i], &w[i])        //sc_mul(tmp.bytes, w[i].bytes, w[i].bytes);
   221  		crypto.ScMul(&tmp2, &winv[i], &winv[i]) //sc_mul(tmp2.bytes, winv[i].bytes, winv[i].bytes);
   222  		//#if 1
   223  		// ge_dsmp cacheL, cacheR;
   224  		// rct::precomp(cacheL, proof.L[i]);
   225  		//rct::precomp(cacheR, proof.R[i]);
   226  
   227  		ProofLi := new(crypto.ExtendedGroupElement)
   228  		ProofLi.FromBytes(&proof.L[i])
   229  
   230  		ProofRi := new(crypto.ExtendedGroupElement)
   231  		ProofRi.FromBytes(&proof.R[i])
   232  
   233  		var ProofLi_precomputed [8]crypto.CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A
   234  		crypto.GePrecompute(&ProofLi_precomputed, ProofLi)
   235  
   236  		var ProofRi_precomputed [8]crypto.CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A
   237  		crypto.GePrecompute(&ProofRi_precomputed, ProofRi)
   238  
   239  		// optimise these at the end only if possible
   240  		crypto.AddKeys3_3(&tmp, &tmp, &ProofLi_precomputed, &tmp2, &ProofRi_precomputed) //rct::addKeys3(tmp, tmp, cacheL, tmp2, cacheR);
   241  		crypto.AddKeys(&pprime, &pprime, &tmp)                                           //rct::addKeys(pprime, pprime, tmp);
   242  
   243  		//#endif
   244  	}
   245  
   246  	crypto.ScMul(&tmp, &proof.t, &x_ip)                                     // sc_mul(tmp.bytes, proof.t.bytes, x_ip.bytes);
   247  	crypto.AddKeys(&pprime, &pprime, crypto.ScalarMultKey(&crypto.H, &tmp)) //rct::addKeys(pprime, pprime, rct::scalarmultKey(rct::H, tmp));
   248  
   249  	crypto.ScMul(&tmp, &proof.a, &proof.b)         //  sc_mul(tmp.bytes, proof.a.bytes, proof.b.bytes);
   250  	crypto.ScMul(&tmp, &tmp, &x_ip)                // sc_mul(tmp.bytes, tmp.bytes, x_ip.bytes);
   251  	tmp = *(crypto.ScalarMultKey(&crypto.H, &tmp)) //tmp = rct::scalarmultKey(rct::H, tmp);
   252  	crypto.AddKeys(&tmp, &tmp, &inner_prod)        //rct::addKeys(tmp, tmp, inner_prod);
   253  
   254  	if !(pprime == tmp) {
   255  		// MERROR("Verification failure at step 2");
   256  		// fmt.Printf("Verification failure at step 2");
   257  		return false
   258  	}
   259  
   260  	//fmt.Printf("\n prime      %s\n tmp %s  bulletproof verified successfully\n", pprime, tmp)
   261  
   262  	return true
   263  }