mirror of
				https://git.wownero.com/wownero/wownero.git
				synced 2024-08-15 01:03:23 +00:00 
			
		
		
		
	CLSAG signatures
This commit is contained in:
		
							parent
							
								
									c695470cff
								
							
						
					
					
						commit
						4b328c6616
					
				
					 12 changed files with 578 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -1234,6 +1234,56 @@ void ge_double_scalarmult_base_vartime(ge_p2 *r, const unsigned char *a, const g
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Computes aG + bB + cC (G is the fixed basepoint)
 | 
			
		||||
void ge_triple_scalarmult_base_vartime(ge_p2 *r, const unsigned char *a, const unsigned char *b, const ge_dsmp Bi, const unsigned char *c, const ge_dsmp Ci) {
 | 
			
		||||
  signed char aslide[256];
 | 
			
		||||
  signed char bslide[256];
 | 
			
		||||
  signed char cslide[256];
 | 
			
		||||
  ge_p1p1 t;
 | 
			
		||||
  ge_p3 u;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  slide(aslide, a);
 | 
			
		||||
  slide(bslide, b);
 | 
			
		||||
  slide(cslide, c);
 | 
			
		||||
 | 
			
		||||
  ge_p2_0(r);
 | 
			
		||||
 | 
			
		||||
  for (i = 255; i >= 0; --i) {
 | 
			
		||||
    if (aslide[i] || bslide[i] || cslide[i]) break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (; i >= 0; --i) {
 | 
			
		||||
    ge_p2_dbl(&t, r);
 | 
			
		||||
 | 
			
		||||
    if (aslide[i] > 0) {
 | 
			
		||||
      ge_p1p1_to_p3(&u, &t);
 | 
			
		||||
      ge_madd(&t, &u, &ge_Bi[aslide[i]/2]);
 | 
			
		||||
    } else if (aslide[i] < 0) {
 | 
			
		||||
      ge_p1p1_to_p3(&u, &t);
 | 
			
		||||
      ge_msub(&t, &u, &ge_Bi[(-aslide[i])/2]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (bslide[i] > 0) {
 | 
			
		||||
      ge_p1p1_to_p3(&u, &t);
 | 
			
		||||
      ge_add(&t, &u, &Bi[bslide[i]/2]);
 | 
			
		||||
    } else if (bslide[i] < 0) {
 | 
			
		||||
      ge_p1p1_to_p3(&u, &t);
 | 
			
		||||
      ge_sub(&t, &u, &Bi[(-bslide[i])/2]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (cslide[i] > 0) {
 | 
			
		||||
      ge_p1p1_to_p3(&u, &t);
 | 
			
		||||
      ge_add(&t, &u, &Ci[cslide[i]/2]);
 | 
			
		||||
    } else if (cslide[i] < 0) {
 | 
			
		||||
      ge_p1p1_to_p3(&u, &t);
 | 
			
		||||
      ge_sub(&t, &u, &Ci[(-cslide[i])/2]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ge_p1p1_to_p2(r, &t);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ge_double_scalarmult_base_vartime_p3(ge_p3 *r3, const unsigned char *a, const ge_p3 *A, const unsigned char *b) {
 | 
			
		||||
  signed char aslide[256];
 | 
			
		||||
  signed char bslide[256];
 | 
			
		||||
| 
						 | 
				
			
			@ -2148,6 +2198,56 @@ void ge_double_scalarmult_precomp_vartime2(ge_p2 *r, const unsigned char *a, con
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Computes aA + bB + cC (all points require precomputation)
 | 
			
		||||
void ge_triple_scalarmult_precomp_vartime(ge_p2 *r, const unsigned char *a, const ge_dsmp Ai, const unsigned char *b, const ge_dsmp Bi, const unsigned char *c, const ge_dsmp Ci) {
 | 
			
		||||
  signed char aslide[256];
 | 
			
		||||
  signed char bslide[256];
 | 
			
		||||
  signed char cslide[256];
 | 
			
		||||
  ge_p1p1 t;
 | 
			
		||||
  ge_p3 u;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  slide(aslide, a);
 | 
			
		||||
  slide(bslide, b);
 | 
			
		||||
  slide(cslide, c);
 | 
			
		||||
 | 
			
		||||
  ge_p2_0(r);
 | 
			
		||||
 | 
			
		||||
  for (i = 255; i >= 0; --i) {
 | 
			
		||||
    if (aslide[i] || bslide[i] || cslide[i]) break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (; i >= 0; --i) {
 | 
			
		||||
    ge_p2_dbl(&t, r);
 | 
			
		||||
 | 
			
		||||
    if (aslide[i] > 0) {
 | 
			
		||||
      ge_p1p1_to_p3(&u, &t);
 | 
			
		||||
      ge_add(&t, &u, &Ai[aslide[i]/2]);
 | 
			
		||||
    } else if (aslide[i] < 0) {
 | 
			
		||||
      ge_p1p1_to_p3(&u, &t);
 | 
			
		||||
      ge_sub(&t, &u, &Ai[(-aslide[i])/2]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (bslide[i] > 0) {
 | 
			
		||||
      ge_p1p1_to_p3(&u, &t);
 | 
			
		||||
      ge_add(&t, &u, &Bi[bslide[i]/2]);
 | 
			
		||||
    } else if (bslide[i] < 0) {
 | 
			
		||||
      ge_p1p1_to_p3(&u, &t);
 | 
			
		||||
      ge_sub(&t, &u, &Bi[(-bslide[i])/2]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (cslide[i] > 0) {
 | 
			
		||||
      ge_p1p1_to_p3(&u, &t);
 | 
			
		||||
      ge_add(&t, &u, &Ci[cslide[i]/2]);
 | 
			
		||||
    } else if (cslide[i] < 0) {
 | 
			
		||||
      ge_p1p1_to_p3(&u, &t);
 | 
			
		||||
      ge_sub(&t, &u, &Ci[(-cslide[i])/2]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ge_p1p1_to_p2(r, &t);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ge_double_scalarmult_precomp_vartime2_p3(ge_p3 *r3, const unsigned char *a, const ge_dsmp Ai, const unsigned char *b, const ge_dsmp Bi) {
 | 
			
		||||
  signed char aslide[256];
 | 
			
		||||
  signed char bslide[256];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,6 +79,7 @@ typedef ge_cached ge_dsmp[8];
 | 
			
		|||
extern const ge_precomp ge_Bi[8];
 | 
			
		||||
void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s);
 | 
			
		||||
void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *);
 | 
			
		||||
void ge_triple_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp);
 | 
			
		||||
void ge_double_scalarmult_base_vartime_p3(ge_p3 *, const unsigned char *, const ge_p3 *, const unsigned char *);
 | 
			
		||||
 | 
			
		||||
/* From ge_frombytes.c, modified */
 | 
			
		||||
| 
						 | 
				
			
			@ -130,6 +131,7 @@ void sc_reduce(unsigned char *);
 | 
			
		|||
void ge_scalarmult(ge_p2 *, const unsigned char *, const ge_p3 *);
 | 
			
		||||
void ge_scalarmult_p3(ge_p3 *, const unsigned char *, const ge_p3 *);
 | 
			
		||||
void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp);
 | 
			
		||||
void ge_triple_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp);
 | 
			
		||||
void ge_double_scalarmult_precomp_vartime2(ge_p2 *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp);
 | 
			
		||||
void ge_double_scalarmult_precomp_vartime2_p3(ge_p3 *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp);
 | 
			
		||||
void ge_mul8(ge_p1p1 *, const ge_p2 *);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -226,6 +226,9 @@ namespace config
 | 
			
		|||
  const unsigned char HASH_KEY_MEMORY = 'k';
 | 
			
		||||
  const unsigned char HASH_KEY_MULTISIG[] = {'M', 'u', 'l', 't' , 'i', 's', 'i', 'g', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 | 
			
		||||
  const unsigned char HASH_KEY_TXPROOF_V2[] = "TXPROOF_V2";
 | 
			
		||||
  const unsigned char HASH_KEY_CLSAG_ROUND[] = "CLSAG_round";
 | 
			
		||||
  const unsigned char HASH_KEY_CLSAG_AGG_0[] = "CLSAG_agg_0";
 | 
			
		||||
  const unsigned char HASH_KEY_CLSAG_AGG_1[] = "CLSAG_agg_1";
 | 
			
		||||
 | 
			
		||||
  namespace testnet
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -511,6 +511,23 @@ namespace rct {
 | 
			
		|||
        ge_tobytes(aAbB.bytes, &rv);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // addKeys_aGbBcC
 | 
			
		||||
    // computes aG + bB + cC
 | 
			
		||||
    // G is the fixed basepoint and B,C require precomputation
 | 
			
		||||
    void addKeys_aGbBcC(key &aGbBcC, const key &a, const key &b, const ge_dsmp B, const key &c, const ge_dsmp C) {
 | 
			
		||||
        ge_p2 rv;
 | 
			
		||||
        ge_triple_scalarmult_base_vartime(&rv, a.bytes, b.bytes, B, c.bytes, C);
 | 
			
		||||
        ge_tobytes(aGbBcC.bytes, &rv);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // addKeys_aAbBcC
 | 
			
		||||
    // computes aA + bB + cC
 | 
			
		||||
    // A,B,C require precomputation
 | 
			
		||||
    void addKeys_aAbBcC(key &aAbBcC, const key &a, const ge_dsmp A, const key &b, const ge_dsmp B, const key &c, const ge_dsmp C) {
 | 
			
		||||
        ge_p2 rv;
 | 
			
		||||
        ge_triple_scalarmult_precomp_vartime(&rv, a.bytes, A, b.bytes, B, c.bytes, C);
 | 
			
		||||
        ge_tobytes(aAbBcC.bytes, &rv);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //subtract Keys (subtracts curve points)
 | 
			
		||||
    //AB = A - B where A, B are curve points
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -145,6 +145,10 @@ namespace rct {
 | 
			
		|||
    //B must be input after applying "precomp"
 | 
			
		||||
    void addKeys3(key &aAbB, const key &a, const key &A, const key &b, const ge_dsmp B);
 | 
			
		||||
    void addKeys3(key &aAbB, const key &a, const ge_dsmp A, const key &b, const ge_dsmp B);
 | 
			
		||||
 | 
			
		||||
    void addKeys_aGbBcC(key &aGbBcC, const key &a, const key &b, const ge_dsmp B, const key &c, const ge_dsmp C);
 | 
			
		||||
    void addKeys_aAbBcC(key &aAbBcC, const key &a, const ge_dsmp A, const key &b, const ge_dsmp B, const key &c, const ge_dsmp C);
 | 
			
		||||
 | 
			
		||||
    //AB = A - B where A, B are curve points
 | 
			
		||||
    void subKeys(key &AB, const key &A, const  key &B);
 | 
			
		||||
    //checks if A, B are equal as curve points
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,6 +36,7 @@
 | 
			
		|||
#include "rctSigs.h"
 | 
			
		||||
#include "bulletproofs.h"
 | 
			
		||||
#include "cryptonote_basic/cryptonote_format_utils.h"
 | 
			
		||||
#include "cryptonote_config.h"
 | 
			
		||||
 | 
			
		||||
using namespace crypto;
 | 
			
		||||
using namespace std;
 | 
			
		||||
| 
						 | 
				
			
			@ -165,6 +166,243 @@ namespace rct {
 | 
			
		|||
      return verifyBorromean(bb, P1_p3, P2_p3);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Generate a CLSAG signature
 | 
			
		||||
    // See paper by Goodell et al. (https://eprint.iacr.org/2019/654)
 | 
			
		||||
    clsag CLSAG_Gen(const key &message, const keyV & P, const key & p, const keyV & C, const key & z, const unsigned int l, const multisig_kLRki *kLRki) {
 | 
			
		||||
        clsag sig;
 | 
			
		||||
        size_t n = P.size(); // ring size
 | 
			
		||||
        CHECK_AND_ASSERT_THROW_MES(n == C.size(), "Signing and commitment key vector sizes must match!");
 | 
			
		||||
        CHECK_AND_ASSERT_THROW_MES(l < n, "Signing index out of range!");
 | 
			
		||||
 | 
			
		||||
        // Key images
 | 
			
		||||
        ge_p3 H_p3;
 | 
			
		||||
        hash_to_p3(H_p3,P[l]);
 | 
			
		||||
        key H;
 | 
			
		||||
        ge_p3_tobytes(H.bytes,&H_p3);
 | 
			
		||||
 | 
			
		||||
        key D;
 | 
			
		||||
        scalarmultKey(D,H,z);
 | 
			
		||||
 | 
			
		||||
        // Multisig
 | 
			
		||||
        if (kLRki)
 | 
			
		||||
        {
 | 
			
		||||
            sig.I = kLRki->ki;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            scalarmultKey(sig.I,H,p);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        geDsmp I_precomp;
 | 
			
		||||
        geDsmp D_precomp;
 | 
			
		||||
        precomp(I_precomp.k,sig.I);
 | 
			
		||||
        precomp(D_precomp.k,D);
 | 
			
		||||
 | 
			
		||||
        // Offset key image
 | 
			
		||||
        scalarmultKey(sig.D,D,INV_EIGHT);
 | 
			
		||||
 | 
			
		||||
        // Initial values
 | 
			
		||||
        key a;
 | 
			
		||||
        key aG;
 | 
			
		||||
        key aH;
 | 
			
		||||
        skpkGen(a,aG);
 | 
			
		||||
        scalarmultKey(aH,H,a);
 | 
			
		||||
 | 
			
		||||
        // Aggregation hashes
 | 
			
		||||
        keyV mu_P_to_hash(2*n+3); // domain, I, D, P, C
 | 
			
		||||
        keyV mu_C_to_hash(2*n+3); // domain, I, D, P, C
 | 
			
		||||
        sc_0(mu_P_to_hash[0].bytes);
 | 
			
		||||
        memcpy(mu_P_to_hash[0].bytes,config::HASH_KEY_CLSAG_AGG_0,sizeof(config::HASH_KEY_CLSAG_AGG_0)-1);
 | 
			
		||||
        sc_0(mu_C_to_hash[0].bytes);
 | 
			
		||||
        memcpy(mu_C_to_hash[0].bytes,config::HASH_KEY_CLSAG_AGG_1,sizeof(config::HASH_KEY_CLSAG_AGG_1)-1);
 | 
			
		||||
        for (size_t i = 1; i < n+1; ++i) {
 | 
			
		||||
            mu_P_to_hash[i] = P[i-1];
 | 
			
		||||
            mu_C_to_hash[i] = P[i-1];
 | 
			
		||||
        }
 | 
			
		||||
        for (size_t i = n+1; i < 2*n+1; ++i) {
 | 
			
		||||
            mu_P_to_hash[i] = C[i-n-1];
 | 
			
		||||
            mu_C_to_hash[i] = C[i-n-1];
 | 
			
		||||
        }
 | 
			
		||||
        mu_P_to_hash[2*n+1] = sig.I;
 | 
			
		||||
        mu_P_to_hash[2*n+2] = sig.D;
 | 
			
		||||
        mu_C_to_hash[2*n+1] = sig.I;
 | 
			
		||||
        mu_C_to_hash[2*n+2] = sig.D;
 | 
			
		||||
        key mu_P, mu_C;
 | 
			
		||||
        mu_P = hash_to_scalar(mu_P_to_hash);
 | 
			
		||||
        mu_C = hash_to_scalar(mu_C_to_hash);
 | 
			
		||||
 | 
			
		||||
        // Initial commitment
 | 
			
		||||
        keyV c_to_hash(2*n+4); // domain, P, C, message, aG, aH
 | 
			
		||||
        key c;
 | 
			
		||||
        sc_0(c_to_hash[0].bytes);
 | 
			
		||||
        memcpy(c_to_hash[0].bytes,config::HASH_KEY_CLSAG_ROUND,sizeof(config::HASH_KEY_CLSAG_ROUND)-1);
 | 
			
		||||
        for (size_t i = 1; i < n+1; ++i)
 | 
			
		||||
        {
 | 
			
		||||
            c_to_hash[i] = P[i-1];
 | 
			
		||||
            c_to_hash[i+n] = C[i-1];
 | 
			
		||||
        }
 | 
			
		||||
        c_to_hash[2*n+1] = message;
 | 
			
		||||
 | 
			
		||||
        // Multisig data is present
 | 
			
		||||
        if (kLRki)
 | 
			
		||||
        {
 | 
			
		||||
            a = kLRki->k;
 | 
			
		||||
            c_to_hash[2*n+2] = kLRki->L;
 | 
			
		||||
            c_to_hash[2*n+3] = kLRki->R;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            c_to_hash[2*n+2] = aG;
 | 
			
		||||
            c_to_hash[2*n+3] = aH;
 | 
			
		||||
        }
 | 
			
		||||
        c = hash_to_scalar(c_to_hash);
 | 
			
		||||
        
 | 
			
		||||
        size_t i;
 | 
			
		||||
        i = (l + 1) % n;
 | 
			
		||||
        if (i == 0)
 | 
			
		||||
            copy(sig.c1, c);
 | 
			
		||||
 | 
			
		||||
        // Decoy indices
 | 
			
		||||
        sig.s = keyV(n);
 | 
			
		||||
        key c_new;
 | 
			
		||||
        key L;
 | 
			
		||||
        key R;
 | 
			
		||||
        key c_p; // = c[i]*mu_P
 | 
			
		||||
        key c_c; // = c[i]*mu_C
 | 
			
		||||
        geDsmp P_precomp;
 | 
			
		||||
        geDsmp C_precomp;
 | 
			
		||||
        geDsmp H_precomp;
 | 
			
		||||
        ge_p3 Hi_p3;
 | 
			
		||||
 | 
			
		||||
        while (i != l) {
 | 
			
		||||
            sig.s[i] = skGen();
 | 
			
		||||
            sc_0(c_new.bytes);
 | 
			
		||||
            sc_mul(c_p.bytes,mu_P.bytes,c.bytes);
 | 
			
		||||
            sc_mul(c_c.bytes,mu_C.bytes,c.bytes);
 | 
			
		||||
 | 
			
		||||
            // Precompute points
 | 
			
		||||
            precomp(P_precomp.k,P[i]);
 | 
			
		||||
            precomp(C_precomp.k,C[i]);
 | 
			
		||||
 | 
			
		||||
            // Compute L
 | 
			
		||||
            addKeys_aGbBcC(L,sig.s[i],c_p,P_precomp.k,c_c,C_precomp.k);
 | 
			
		||||
 | 
			
		||||
            // Compute R
 | 
			
		||||
            hash_to_p3(Hi_p3,P[i]);
 | 
			
		||||
            ge_dsm_precomp(H_precomp.k, &Hi_p3);
 | 
			
		||||
            addKeys_aAbBcC(R,sig.s[i],H_precomp.k,c_p,I_precomp.k,c_c,D_precomp.k);
 | 
			
		||||
 | 
			
		||||
            c_to_hash[2*n+2] = L;
 | 
			
		||||
            c_to_hash[2*n+3] = R;
 | 
			
		||||
            c_new = hash_to_scalar(c_to_hash);
 | 
			
		||||
            copy(c,c_new);
 | 
			
		||||
            
 | 
			
		||||
            i = (i + 1) % n;
 | 
			
		||||
            if (i == 0)
 | 
			
		||||
                copy(sig.c1,c);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Compute final scalar
 | 
			
		||||
        key s0_p_mu_P;
 | 
			
		||||
        sc_mul(s0_p_mu_P.bytes,mu_P.bytes,p.bytes);
 | 
			
		||||
        key s0_add_z_mu_C;
 | 
			
		||||
        sc_muladd(s0_add_z_mu_C.bytes,mu_C.bytes,z.bytes,s0_p_mu_P.bytes);
 | 
			
		||||
        sc_mulsub(sig.s[l].bytes,c.bytes,s0_add_z_mu_C.bytes,a.bytes);
 | 
			
		||||
 | 
			
		||||
        return sig;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Verify a CLSAG signature
 | 
			
		||||
    // See paper by Goodell et al. (https://eprint.iacr.org/2019/654)
 | 
			
		||||
    bool CLSAG_Ver(const key &message, const keyV & P, const keyV & C, const clsag & sig)
 | 
			
		||||
    {
 | 
			
		||||
        size_t n = P.size(); // ring size
 | 
			
		||||
        CHECK_AND_ASSERT_MES(n == C.size(), false, "Signing and commitment key vector sizes must match!");
 | 
			
		||||
        CHECK_AND_ASSERT_MES(n == sig.s.size(), false, "Signature scalar vector is the wrong size!");
 | 
			
		||||
        for (size_t i = 0; i < n; ++i)
 | 
			
		||||
            CHECK_AND_ASSERT_MES(sc_check(sig.s[i].bytes) == 0, false, "Bad signature scalar!");
 | 
			
		||||
        CHECK_AND_ASSERT_MES(sc_check(sig.c1.bytes) == 0, false, "Bad signature commitment!");
 | 
			
		||||
 | 
			
		||||
        key c = copy(sig.c1);
 | 
			
		||||
        key D_8 = scalarmult8(sig.D);
 | 
			
		||||
        geDsmp I_precomp;
 | 
			
		||||
        geDsmp D_precomp;
 | 
			
		||||
        precomp(I_precomp.k,sig.I);
 | 
			
		||||
        precomp(D_precomp.k,D_8);
 | 
			
		||||
 | 
			
		||||
        // Aggregation hashes
 | 
			
		||||
        keyV mu_P_to_hash(2*n+3); // domain, I, D, P, C
 | 
			
		||||
        keyV mu_C_to_hash(2*n+3); // domain, I, D, P, C
 | 
			
		||||
        sc_0(mu_P_to_hash[0].bytes);
 | 
			
		||||
        memcpy(mu_P_to_hash[0].bytes,config::HASH_KEY_CLSAG_AGG_0,sizeof(config::HASH_KEY_CLSAG_AGG_0)-1);
 | 
			
		||||
        sc_0(mu_C_to_hash[0].bytes);
 | 
			
		||||
        memcpy(mu_C_to_hash[0].bytes,config::HASH_KEY_CLSAG_AGG_1,sizeof(config::HASH_KEY_CLSAG_AGG_1)-1);
 | 
			
		||||
        for (size_t i = 1; i < n+1; ++i) {
 | 
			
		||||
            mu_P_to_hash[i] = P[i-1];
 | 
			
		||||
            mu_C_to_hash[i] = P[i-1];
 | 
			
		||||
        }
 | 
			
		||||
        for (size_t i = n+1; i < 2*n+1; ++i) {
 | 
			
		||||
            mu_P_to_hash[i] = C[i-n-1];
 | 
			
		||||
            mu_C_to_hash[i] = C[i-n-1];
 | 
			
		||||
        }
 | 
			
		||||
        mu_P_to_hash[2*n+1] = sig.I;
 | 
			
		||||
        mu_P_to_hash[2*n+2] = sig.D;
 | 
			
		||||
        mu_C_to_hash[2*n+1] = sig.I;
 | 
			
		||||
        mu_C_to_hash[2*n+2] = sig.D;
 | 
			
		||||
        key mu_P, mu_C;
 | 
			
		||||
        mu_P = hash_to_scalar(mu_P_to_hash);
 | 
			
		||||
        mu_C = hash_to_scalar(mu_C_to_hash);
 | 
			
		||||
 | 
			
		||||
        keyV c_to_hash(2*n+4); // domain, P, C, message, L, R
 | 
			
		||||
        sc_0(c_to_hash[0].bytes);
 | 
			
		||||
        memcpy(c_to_hash[0].bytes,config::HASH_KEY_CLSAG_ROUND,sizeof(config::HASH_KEY_CLSAG_ROUND)-1);
 | 
			
		||||
        for (size_t i = 1; i < n+1; ++i)
 | 
			
		||||
        {
 | 
			
		||||
            c_to_hash[i] = P[i-1];
 | 
			
		||||
            c_to_hash[i+n] = C[i-1];
 | 
			
		||||
        }
 | 
			
		||||
        c_to_hash[2*n+1] = message;
 | 
			
		||||
        key c_p; // = c[i]*mu_P
 | 
			
		||||
        key c_c; // = c[i]*mu_C
 | 
			
		||||
        key c_new;
 | 
			
		||||
        key L;
 | 
			
		||||
        key R;
 | 
			
		||||
        geDsmp P_precomp;
 | 
			
		||||
        geDsmp C_precomp;
 | 
			
		||||
        geDsmp H_precomp;
 | 
			
		||||
        size_t i = 0;
 | 
			
		||||
        ge_p3 hash8_p3;
 | 
			
		||||
        geDsmp hash_precomp;
 | 
			
		||||
 | 
			
		||||
        while (i < n) {
 | 
			
		||||
            sc_0(c_new.bytes);
 | 
			
		||||
            sc_mul(c_p.bytes,mu_P.bytes,c.bytes);
 | 
			
		||||
            sc_mul(c_c.bytes,mu_C.bytes,c.bytes);
 | 
			
		||||
 | 
			
		||||
            // Precompute points
 | 
			
		||||
            precomp(P_precomp.k,P[i]);
 | 
			
		||||
            precomp(C_precomp.k,C[i]);
 | 
			
		||||
 | 
			
		||||
            // Compute L
 | 
			
		||||
            addKeys_aGbBcC(L,sig.s[i],c_p,P_precomp.k,c_c,C_precomp.k);
 | 
			
		||||
 | 
			
		||||
            // Compute R
 | 
			
		||||
            hash_to_p3(hash8_p3,P[i]);
 | 
			
		||||
            ge_dsm_precomp(hash_precomp.k, &hash8_p3);
 | 
			
		||||
            addKeys_aAbBcC(R,sig.s[i],hash_precomp.k,c_p,I_precomp.k,c_c,D_precomp.k);
 | 
			
		||||
 | 
			
		||||
            c_to_hash[2*n+2] = L;
 | 
			
		||||
            c_to_hash[2*n+3] = R;
 | 
			
		||||
            c_new = hash_to_scalar(c_to_hash);
 | 
			
		||||
            CHECK_AND_ASSERT_MES(!(c_new == rct::zero()), false, "Bad signature hash");
 | 
			
		||||
            copy(c,c_new);
 | 
			
		||||
 | 
			
		||||
            i = i + 1;
 | 
			
		||||
        }
 | 
			
		||||
        sc_sub(c_new.bytes,c.bytes,sig.c1.bytes);
 | 
			
		||||
        return sc_isnonzero(c_new.bytes) == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // MLSAG signatures
 | 
			
		||||
    // See paper by Noether (https://eprint.iacr.org/2015/1098)
 | 
			
		||||
    // This generalization allows for some dimensions not to require linkability;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,6 +76,9 @@ namespace rct {
 | 
			
		|||
    // Ver verifies that the MG sig was created correctly
 | 
			
		||||
    mgSig MLSAG_Gen(const key &message, const keyM & pk, const keyV & xx, const multisig_kLRki *kLRki, key *mscout, const unsigned int index, size_t dsRows, hw::device &hwdev);
 | 
			
		||||
    bool MLSAG_Ver(const key &message, const keyM &pk, const mgSig &sig, size_t dsRows);
 | 
			
		||||
 | 
			
		||||
    clsag CLSAG_Gen(const key &message, const keyV & P, const key & p, const keyV & C, const key & z, const unsigned int l, const multisig_kLRki *kLRki);
 | 
			
		||||
    bool CLSAG_Ver(const key &message, const keyV & P, const keyV & C, const clsag & sig);
 | 
			
		||||
    //mgSig MLSAG_Gen_Old(const keyM & pk, const keyV & xx, const int index);
 | 
			
		||||
 | 
			
		||||
    //proveRange and verRange
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -163,6 +163,21 @@ namespace rct {
 | 
			
		|||
            // FIELD(II) - not serialized, it can be reconstructed
 | 
			
		||||
        END_SERIALIZE()
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // CLSAG signature
 | 
			
		||||
    struct clsag {
 | 
			
		||||
        keyV s; // scalars
 | 
			
		||||
        key c1;
 | 
			
		||||
 | 
			
		||||
        key I; // signing key image
 | 
			
		||||
        key D; // commitment key image
 | 
			
		||||
 | 
			
		||||
        BEGIN_SERIALIZE_OBJECT()
 | 
			
		||||
            FIELD(s)
 | 
			
		||||
            FIELD(c1)
 | 
			
		||||
        END_SERIALIZE()
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //contains the data for an Borromean sig
 | 
			
		||||
    // also contains the "Ci" values such that
 | 
			
		||||
    // \sum Ci = C
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,11 +51,15 @@ enum test_op
 | 
			
		|||
  op_scalarmult8_p3,
 | 
			
		||||
  op_ge_dsm_precomp,
 | 
			
		||||
  op_ge_double_scalarmult_base_vartime,
 | 
			
		||||
  op_ge_triple_scalarmult_base_vartime,
 | 
			
		||||
  op_ge_double_scalarmult_precomp_vartime,
 | 
			
		||||
  op_ge_triple_scalarmult_precomp_vartime,
 | 
			
		||||
  op_ge_double_scalarmult_precomp_vartime2,
 | 
			
		||||
  op_addKeys2,
 | 
			
		||||
  op_addKeys3,
 | 
			
		||||
  op_addKeys3_2,
 | 
			
		||||
  op_addKeys_aGbBcC,
 | 
			
		||||
  op_addKeys_aAbBcC,
 | 
			
		||||
  op_isInMainSubgroup,
 | 
			
		||||
  op_zeroCommitUncached,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -70,15 +74,20 @@ public:
 | 
			
		|||
  {
 | 
			
		||||
    scalar0 = rct::skGen();
 | 
			
		||||
    scalar1 = rct::skGen();
 | 
			
		||||
    scalar2 = rct::skGen();
 | 
			
		||||
    point0 = rct::scalarmultBase(rct::skGen());
 | 
			
		||||
    point1 = rct::scalarmultBase(rct::skGen());
 | 
			
		||||
    point2 = rct::scalarmultBase(rct::skGen());
 | 
			
		||||
    if (ge_frombytes_vartime(&p3_0, point0.bytes) != 0)
 | 
			
		||||
      return false;
 | 
			
		||||
    if (ge_frombytes_vartime(&p3_1, point1.bytes) != 0)
 | 
			
		||||
      return false;
 | 
			
		||||
    if (ge_frombytes_vartime(&p3_2, point2.bytes) != 0)
 | 
			
		||||
      return false;
 | 
			
		||||
    ge_p3_to_cached(&cached, &p3_0);
 | 
			
		||||
    rct::precomp(precomp0, point0);
 | 
			
		||||
    rct::precomp(precomp1, point1);
 | 
			
		||||
    rct::precomp(precomp2, point2);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -109,11 +118,15 @@ public:
 | 
			
		|||
      case op_scalarmult8_p3: rct::scalarmult8(p3_0,point0); break;
 | 
			
		||||
      case op_ge_dsm_precomp: ge_dsm_precomp(dsmp, &p3_0); break;
 | 
			
		||||
      case op_ge_double_scalarmult_base_vartime: ge_double_scalarmult_base_vartime(&tmp_p2, scalar0.bytes, &p3_0, scalar1.bytes); break;
 | 
			
		||||
      case op_ge_triple_scalarmult_base_vartime: ge_triple_scalarmult_base_vartime(&tmp_p2, scalar0.bytes, scalar1.bytes, precomp1, scalar2.bytes, precomp2); break;
 | 
			
		||||
      case op_ge_double_scalarmult_precomp_vartime: ge_double_scalarmult_precomp_vartime(&tmp_p2, scalar0.bytes, &p3_0, scalar1.bytes, precomp0); break;
 | 
			
		||||
      case op_ge_triple_scalarmult_precomp_vartime: ge_triple_scalarmult_precomp_vartime(&tmp_p2, scalar0.bytes, precomp0, scalar1.bytes, precomp1, scalar2.bytes, precomp2); break;
 | 
			
		||||
      case op_ge_double_scalarmult_precomp_vartime2: ge_double_scalarmult_precomp_vartime2(&tmp_p2, scalar0.bytes, precomp0, scalar1.bytes, precomp1); break;
 | 
			
		||||
      case op_addKeys2: rct::addKeys2(key, scalar0, scalar1, point0); break;
 | 
			
		||||
      case op_addKeys3: rct::addKeys3(key, scalar0, point0, scalar1, precomp1); break;
 | 
			
		||||
      case op_addKeys3_2: rct::addKeys3(key, scalar0, precomp0, scalar1, precomp1); break;
 | 
			
		||||
      case op_addKeys_aGbBcC: rct::addKeys_aGbBcC(key, scalar0, scalar1, precomp1, scalar2, precomp2); break;
 | 
			
		||||
      case op_addKeys_aAbBcC: rct::addKeys_aAbBcC(key, scalar0, precomp0, scalar1, precomp1, scalar2, precomp2); break;
 | 
			
		||||
      case op_isInMainSubgroup: rct::isInMainSubgroup(point0); break;
 | 
			
		||||
      case op_zeroCommitUncached: rct::zeroCommit(9001); break;
 | 
			
		||||
      case op_zeroCommitCached: rct::zeroCommit(9000); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -123,9 +136,9 @@ public:
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  rct::key scalar0, scalar1;
 | 
			
		||||
  rct::key point0, point1;
 | 
			
		||||
  ge_p3 p3_0, p3_1;
 | 
			
		||||
  rct::key scalar0, scalar1, scalar2;
 | 
			
		||||
  rct::key point0, point1, point2;
 | 
			
		||||
  ge_p3 p3_0, p3_1, p3_2;
 | 
			
		||||
  ge_cached cached;
 | 
			
		||||
  ge_dsmp precomp0, precomp1;
 | 
			
		||||
  ge_dsmp precomp0, precomp1, precomp2;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,6 +60,8 @@
 | 
			
		|||
#include "bulletproof.h"
 | 
			
		||||
#include "crypto_ops.h"
 | 
			
		||||
#include "multiexp.h"
 | 
			
		||||
#include "sig_mlsag.h"
 | 
			
		||||
#include "sig_clsag.h"
 | 
			
		||||
 | 
			
		||||
namespace po = boost::program_options;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -213,6 +215,9 @@ int main(int argc, char** argv)
 | 
			
		|||
  TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 32);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 16384);
 | 
			
		||||
 | 
			
		||||
  TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 11, true); // MLSAG verification
 | 
			
		||||
  TEST_PERFORMANCE3(filter, p, test_sig_clsag, 11, true, 0); // CLSAG verification
 | 
			
		||||
 | 
			
		||||
  TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, false);
 | 
			
		||||
  TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, true);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -257,11 +262,15 @@ int main(int argc, char** argv)
 | 
			
		|||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmult8_p3);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_dsm_precomp);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_base_vartime);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_triple_scalarmult_base_vartime);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_precomp_vartime);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_triple_scalarmult_precomp_vartime);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_precomp_vartime2);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys2);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys3);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys3_2);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys_aGbBcC);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys_aAbBcC);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_isInMainSubgroup);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_zeroCommitUncached);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_zeroCommitCached);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										83
									
								
								tests/performance_tests/sig_clsag.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								tests/performance_tests/sig_clsag.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
// Copyright (c) 2014-2019, The Monero Project
 | 
			
		||||
// 
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
// 
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without modification, are
 | 
			
		||||
// permitted provided that the following conditions are met:
 | 
			
		||||
// 
 | 
			
		||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
 | 
			
		||||
//    conditions and the following disclaimer.
 | 
			
		||||
// 
 | 
			
		||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
 | 
			
		||||
//    of conditions and the following disclaimer in the documentation and/or other
 | 
			
		||||
//    materials provided with the distribution.
 | 
			
		||||
// 
 | 
			
		||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
 | 
			
		||||
//    used to endorse or promote products derived from this software without specific
 | 
			
		||||
//    prior written permission.
 | 
			
		||||
// 
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 | 
			
		||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 | 
			
		||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | 
			
		||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 | 
			
		||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 | 
			
		||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
// 
 | 
			
		||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "ringct/rctSigs.h"
 | 
			
		||||
#include "cryptonote_basic/cryptonote_basic.h"
 | 
			
		||||
 | 
			
		||||
#include "single_tx_test_base.h"
 | 
			
		||||
 | 
			
		||||
template<size_t ring_size, bool ver, size_t index>
 | 
			
		||||
class test_sig_clsag : public single_tx_test_base
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  static const size_t n = ring_size;
 | 
			
		||||
  static const size_t loop_count = 1000;
 | 
			
		||||
  static const size_t l = index;
 | 
			
		||||
 | 
			
		||||
  bool init()
 | 
			
		||||
  {
 | 
			
		||||
    if (!single_tx_test_base::init())
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    p = rct::skGen();
 | 
			
		||||
    z = rct::skGen();
 | 
			
		||||
    P = rct::skvGen(n);
 | 
			
		||||
    C = rct::skvGen(n);
 | 
			
		||||
    for (size_t i = 0 ; i < n; i++)
 | 
			
		||||
    {
 | 
			
		||||
        P[i] = rct::scalarmultBase(P[i]);
 | 
			
		||||
        C[i] = rct::scalarmultBase(C[i]);
 | 
			
		||||
    }
 | 
			
		||||
    P[l] = rct::scalarmultBase(p);
 | 
			
		||||
    C[l] = rct::scalarmultBase(z);
 | 
			
		||||
    
 | 
			
		||||
    sig = CLSAG_Gen(rct::identity(),P,p,C,z,l,NULL);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool test()
 | 
			
		||||
  {
 | 
			
		||||
    if (ver)
 | 
			
		||||
      return CLSAG_Ver(rct::identity(),P,C,sig);
 | 
			
		||||
    else
 | 
			
		||||
      CLSAG_Gen(rct::identity(),P,p,C,z,l,NULL);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  rct::key p;
 | 
			
		||||
  rct::key z;
 | 
			
		||||
  rct::keyV P;
 | 
			
		||||
  rct::keyV C;
 | 
			
		||||
  rct::clsag sig;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										87
									
								
								tests/performance_tests/sig_mlsag.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								tests/performance_tests/sig_mlsag.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,87 @@
 | 
			
		|||
// Copyright (c) 2014-2019, The Monero Project
 | 
			
		||||
// 
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
// 
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without modification, are
 | 
			
		||||
// permitted provided that the following conditions are met:
 | 
			
		||||
// 
 | 
			
		||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
 | 
			
		||||
//    conditions and the following disclaimer.
 | 
			
		||||
// 
 | 
			
		||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
 | 
			
		||||
//    of conditions and the following disclaimer in the documentation and/or other
 | 
			
		||||
//    materials provided with the distribution.
 | 
			
		||||
// 
 | 
			
		||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
 | 
			
		||||
//    used to endorse or promote products derived from this software without specific
 | 
			
		||||
//    prior written permission.
 | 
			
		||||
// 
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 | 
			
		||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 | 
			
		||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | 
			
		||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 | 
			
		||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 | 
			
		||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
// 
 | 
			
		||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "ringct/rctSigs.h"
 | 
			
		||||
#include "cryptonote_basic/cryptonote_basic.h"
 | 
			
		||||
 | 
			
		||||
#include "single_tx_test_base.h"
 | 
			
		||||
 | 
			
		||||
template<size_t ring_size, bool ver>
 | 
			
		||||
class test_sig_mlsag : public single_tx_test_base
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  static const size_t cols = ring_size;
 | 
			
		||||
  static const size_t rows = 2; // 1 spend + 1 commitment
 | 
			
		||||
  static const size_t loop_count = 1000;
 | 
			
		||||
 | 
			
		||||
  bool init()
 | 
			
		||||
  {
 | 
			
		||||
    if (!single_tx_test_base::init())
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    rct::keyV xtmp = rct::skvGen(rows);
 | 
			
		||||
    rct::keyM xm = rct::keyMInit(rows, cols);// = [[None]*N] #just used to generate test public keys
 | 
			
		||||
    sk = rct::skvGen(rows);
 | 
			
		||||
    P  = rct::keyMInit(rows, cols);// = keyM[[None]*N] #stores the public keys;
 | 
			
		||||
    ind = 0; // fixed spend index
 | 
			
		||||
    for (size_t j = 0 ; j < rows ; j++)
 | 
			
		||||
    {
 | 
			
		||||
        for (size_t i = 0 ; i < cols ; i++)
 | 
			
		||||
        {
 | 
			
		||||
            xm[i][j] = rct::skGen();
 | 
			
		||||
            P[i][j] = rct::scalarmultBase(xm[i][j]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    for (size_t j = 0 ; j < rows ; j++)
 | 
			
		||||
    {
 | 
			
		||||
        sk[j] = xm[ind][j];
 | 
			
		||||
    }
 | 
			
		||||
    IIccss = MLSAG_Gen(rct::identity(), P, sk, NULL, NULL, ind, rows-1, hw::get_device("default"));
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool test()
 | 
			
		||||
  {
 | 
			
		||||
    if (ver)
 | 
			
		||||
      return MLSAG_Ver(rct::identity(), P, IIccss, rows-1);
 | 
			
		||||
    else
 | 
			
		||||
      MLSAG_Gen(rct::identity(), P, sk, NULL, NULL, ind, rows-1, hw::get_device("default"));
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  rct::keyV sk;
 | 
			
		||||
  rct::keyM P;
 | 
			
		||||
  size_t ind;
 | 
			
		||||
  rct::mgSig IIccss;
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue