Beispiel #1
0
void sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
{
  sph_sha256_context ctx_sha2;

  sph_sha256_init(&ctx_sha2);
  sph_sha256(&ctx_sha2, message, len);
  sph_sha256_close(&ctx_sha2, (void*)digest);
}
Beispiel #2
0
void gen_hash(const unsigned char *data, unsigned int len, unsigned char *hash)
{
  unsigned char hash1[32];
  sph_sha256_context ctx_sha2;

  sph_sha256_init(&ctx_sha2);
  sph_sha256(&ctx_sha2, data, len);
  sph_sha256_close(&ctx_sha2, hash1);
  sph_sha256(&ctx_sha2, hash1, 32);
  sph_sha256_close(&ctx_sha2, hash);
}
Beispiel #3
0
void sha256d_midstate(struct work *work)
{
  unsigned char data[64];
  uint32_t *data32 = (uint32_t *)data;
  sph_sha256_context ctx;

  flip64(data32, work->data);
  sph_sha256_init(&ctx);
  sph_sha256(&ctx, data, 64);
  memcpy(work->midstate, ctx.val, 32);
  endian_flip32(work->midstate, work->midstate);
}
Beispiel #4
0
void protoshares_process_512(blockHeader_t* block, CBlockProvider* bp, unsigned int thread_id, GPUHasher *_gpu, uint64_t *hashblock)
{
  // generate mid hash using sha256 (header hash)
  uint8_t midHash[32+4];
  {
    //SPH
    sph_sha256_context c256;
    sph_sha256_init(&c256);
    sph_sha256(&c256, (unsigned char*)block, 80);
    sph_sha256_close(&c256, midHash+4);
    sph_sha256_init(&c256);
    sph_sha256(&c256, (unsigned char*)(midHash+4), 32);
    sph_sha256_close(&c256, midHash+4);
  }

  SHA512_Context c512_avxsse;
  
  SHA512_Init(&c512_avxsse);
  SHA512_Update_Simple(&c512_avxsse, midHash, 32+4);
  SHA512_PreFinal(&c512_avxsse);

  *(uint32_t *)(&c512_avxsse.buffer.bytes[0]) = 0;
  _gpu->ComputeHashes((uint64_t *)c512_avxsse.buffer.bytes, hashblock);
  uint32_t n_hashes_plus_one = *((uint32_t *)hashblock);
  boost::unordered_map<uint64_t, uint32_t> resmap;

  for (uint32_t i = 0; i < (n_hashes_plus_one-1); i++) {
    uint64_t birthday = hashblock[1+i*2];
    uint32_t mine = hashblock[1+i*2+1];
    boost::unordered_map<uint64_t,uint32_t>::const_iterator r = resmap.find(birthday);
    if (r != resmap.end()) {
      uint32_t other = r->second;
      protoshares_revalidateCollision<shamode>(block, midHash+4, other, mine, birthday, bp, thread_id);
    }
    resmap[birthday] = mine;
  }
}
Beispiel #5
0
inline void mghash(void *state, const void *input)
{
    sph_groestl512_context ctx_groestl;
    sph_sha256_context ctx_sha2;

    uint32_t hash[16];

    sph_groestl512_init(&ctx_groestl);
    sph_groestl512(&ctx_groestl, input, 80);
    sph_groestl512_close(&ctx_groestl, (void*) hash);
    
    sph_sha256_init(&ctx_sha2);
    sph_sha256(&ctx_sha2, hash, 64);
    sph_sha256_close(&ctx_sha2, (void*) hash);

    memcpy(state, hash, 32);
}
Beispiel #6
0
void lbry_hash(const char* input, char* output, uint32_t len)
{
	uint32_t hashA[16] = { 0 }, hashB[8], hashC[8];
	
	//lbry hash is designed to hash exactly 112 bytes (block header size)
	//so only calculate a hash if 112 bytes are available
	if(len >= 112) {
		sph_sha256_context ctx_sha256;
		sph_sha512_context ctx_sha512;
		sph_ripemd160_context ctx_ripemd;

		sph_sha256_init(&ctx_sha256);
		sph_sha512_init(&ctx_sha512);
		sph_ripemd160_init(&ctx_ripemd);

		sph_sha256(&ctx_sha256, input, 112);
		sph_sha256_close(&ctx_sha256, hashA);

		sph_sha256(&ctx_sha256, hashA, 32);
		sph_sha256_close(&ctx_sha256, hashA);

		sph_sha512(&ctx_sha512, hashA, 32);
		sph_sha512_close(&ctx_sha512, hashA);

		sph_ripemd160(&ctx_ripemd, hashA, 32);
		sph_ripemd160_close(&ctx_ripemd, hashB);

		sph_ripemd160(&ctx_ripemd, &hashA[8], 32);
		sph_ripemd160_close(&ctx_ripemd, hashC);

		sph_sha256(&ctx_sha256, hashB, 20);
		sph_sha256(&ctx_sha256, hashC, 20);
		sph_sha256_close(&ctx_sha256, hashA);

		sph_sha256(&ctx_sha256, hashA, 32);
		sph_sha256_close(&ctx_sha256, hashA);
	}

	memcpy(output, hashA, 32);
}
Beispiel #7
0
/* see sph_sha2.h */
void
sph_sha256_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
{
	sha224_addbits_and_close(cc, ub, n, dst, 8);
	sph_sha256_init((sph_sha256_context*)cc);
}
Beispiel #8
0
/* see sph_sha2.h */
void
sph_sha256_close(void *cc, void *dst)
{
	sha224_close(cc, dst, 8);
	sph_sha256_init((sph_sha256_context*)cc);
}
Beispiel #9
0
bool protoshares_revalidateCollision(blockHeader_t* block, uint8_t* midHash, uint32_t indexA, uint32_t indexB, uint64_t birthday, CBlockProvider* bp, unsigned int thread_id)
{
  uint8_t tempHash[32+4];
  memcpy(tempHash+4, midHash, 32);
  totalCollisionCount += 2; // we can use every collision twice -> A B and B A (srsly?)
  //printf("Collision found %8d = %8d | num: %d\n", indexA, indexB, totalCollisionCount);
        
  sph_sha256_context c256; //SPH
		
  // get full block hash (for A B)
  block->birthdayA = indexA;
  block->birthdayB = indexB;
  uint8_t proofOfWorkHash[32];        
  //SPH
  sph_sha256_init(&c256);
  sph_sha256(&c256, (unsigned char*)block, 80+8);
  sph_sha256_close(&c256, proofOfWorkHash);
  sph_sha256_init(&c256);
  sph_sha256(&c256, (unsigned char*)proofOfWorkHash, 32);
  sph_sha256_close(&c256, proofOfWorkHash);
  bool hashMeetsTarget = true;
  uint32_t* generatedHash32 = (uint32_t*)proofOfWorkHash;
  uint32_t* targetHash32 = (uint32_t*)block->targetShare;
  for(uint64_t hc=7; hc!=0; hc--)
    {
      if( generatedHash32[hc] < targetHash32[hc] )
	{
	  hashMeetsTarget = true;
	  break;
	}
      else if( generatedHash32[hc] > targetHash32[hc] )
	{
	  hashMeetsTarget = false;
	  break;
	}
    }
  if( hashMeetsTarget )
    bp->submitBlock(block, thread_id);
		
  // get full block hash (for B A)
  block->birthdayA = indexB;
  block->birthdayB = indexA;
  //SPH
  sph_sha256_init(&c256);
  sph_sha256(&c256, (unsigned char*)block, 80+8);
  sph_sha256_close(&c256, proofOfWorkHash);
  sph_sha256_init(&c256);
  sph_sha256(&c256, (unsigned char*)proofOfWorkHash, 32);
  sph_sha256_close(&c256, proofOfWorkHash);
  hashMeetsTarget = true;
  generatedHash32 = (uint32_t*)proofOfWorkHash;
  targetHash32 = (uint32_t*)block->targetShare;
  for(uint64_t hc=7; hc!=0; hc--)
    {
      if( generatedHash32[hc] < targetHash32[hc] )
	{
	  hashMeetsTarget = true;
	  break;
	}
      else if( generatedHash32[hc] > targetHash32[hc] )
	{
	  hashMeetsTarget = false;
	  break;
	}
    }
  if( hashMeetsTarget )
    bp->submitBlock(block, thread_id);

  return true;
}
Beispiel #10
0
int scanhash_m7m_hash(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
    uint64_t max_nonce, unsigned long *hashes_done)
{
    uint32_t data[32] __attribute__((aligned(128)));
    uint32_t *data_p64 = data + (M7_MIDSTATE_LEN / sizeof(data[0]));
    uint32_t hash[8] __attribute__((aligned(32)));
    uint8_t bhash[7][64] __attribute__((aligned(32)));
    uint32_t n = pdata[19] - 1;
    const uint32_t first_nonce = pdata[19];
    char data_str[161], hash_str[65], target_str[65];
    uint8_t *bdata = 0;
    mpz_t bns[8];
    int rc = 0;
    int bytes, nnNonce2;

    mpz_t product;
    mpz_init(product);

    for(int i=0; i < 8; i++){
        mpz_init(bns[i]);
    }

    memcpy(data, pdata, 80);

    sph_sha256_context       ctx_final_sha256;

    sph_sha256_context       ctx_sha256;
    sph_sha512_context       ctx_sha512;
    sph_keccak512_context    ctx_keccak;
    sph_whirlpool_context    ctx_whirlpool;
    sph_haval256_5_context   ctx_haval;
    sph_tiger_context        ctx_tiger;
    sph_ripemd160_context    ctx_ripemd;

    sph_sha256_init(&ctx_sha256);
    sph_sha256 (&ctx_sha256, data, M7_MIDSTATE_LEN);
    
    sph_sha512_init(&ctx_sha512);
    sph_sha512 (&ctx_sha512, data, M7_MIDSTATE_LEN);
    
    sph_keccak512_init(&ctx_keccak);
    sph_keccak512 (&ctx_keccak, data, M7_MIDSTATE_LEN);

    sph_whirlpool_init(&ctx_whirlpool);
    sph_whirlpool (&ctx_whirlpool, data, M7_MIDSTATE_LEN);
    
    sph_haval256_5_init(&ctx_haval);
    sph_haval256_5 (&ctx_haval, data, M7_MIDSTATE_LEN);

    sph_tiger_init(&ctx_tiger);
    sph_tiger (&ctx_tiger, data, M7_MIDSTATE_LEN);

    sph_ripemd160_init(&ctx_ripemd);
    sph_ripemd160 (&ctx_ripemd, data, M7_MIDSTATE_LEN);

    sph_sha256_context       ctx2_sha256;
    sph_sha512_context       ctx2_sha512;
    sph_keccak512_context    ctx2_keccak;
    sph_whirlpool_context    ctx2_whirlpool;
    sph_haval256_5_context   ctx2_haval;
    sph_tiger_context        ctx2_tiger;
    sph_ripemd160_context    ctx2_ripemd;

    do {
        data[19] = ++n;
        nnNonce2 = (int)(data[19]/2);
        memset(bhash, 0, 7 * 64);

        ctx2_sha256 = ctx_sha256;
        sph_sha256 (&ctx2_sha256, data_p64, 80 - M7_MIDSTATE_LEN);
        sph_sha256_close(&ctx2_sha256, (void*)(bhash[0]));

        ctx2_sha512 = ctx_sha512;
        sph_sha512 (&ctx2_sha512, data_p64, 80 - M7_MIDSTATE_LEN);
        sph_sha512_close(&ctx2_sha512, (void*)(bhash[1]));
        
        ctx2_keccak = ctx_keccak;
        sph_keccak512 (&ctx2_keccak, data_p64, 80 - M7_MIDSTATE_LEN);
        sph_keccak512_close(&ctx2_keccak, (void*)(bhash[2]));

        ctx2_whirlpool = ctx_whirlpool;
        sph_whirlpool (&ctx2_whirlpool, data_p64, 80 - M7_MIDSTATE_LEN);
        sph_whirlpool_close(&ctx2_whirlpool, (void*)(bhash[3]));
        
        ctx2_haval = ctx_haval;
        sph_haval256_5 (&ctx2_haval, data_p64, 80 - M7_MIDSTATE_LEN);
        sph_haval256_5_close(&ctx2_haval, (void*)(bhash[4]));

        ctx2_tiger = ctx_tiger;
        sph_tiger (&ctx2_tiger, data_p64, 80 - M7_MIDSTATE_LEN);
        sph_tiger_close(&ctx2_tiger, (void*)(bhash[5]));

        ctx2_ripemd = ctx_ripemd;
        sph_ripemd160 (&ctx2_ripemd, data_p64, 80 - M7_MIDSTATE_LEN);
        sph_ripemd160_close(&ctx2_ripemd, (void*)(bhash[6]));

        for(int i=0; i < 7; i++){
            set_one_if_zero(bhash[i]);
            mpz_set_uint512(bns[i],bhash[i]);
        }

        mpz_set_ui(bns[7],0);

        for(int i=0; i < 7; i++){
	        mpz_add(bns[7], bns[7], bns[i]);
        }

        mpz_set_ui(product,1);

        for(int i=0; i < 8; i++){
            mpz_mul(product,product,bns[i]);
        }

        mpz_pow_ui(product, product, 2); 

        bytes = mpz_sizeinbase(product, 256);
        bdata = (uint8_t *)realloc(bdata, bytes);
        mpz_export((void *)bdata, NULL, -1, 1, 0, 0, product);

        sph_sha256_init(&ctx_final_sha256);
        sph_sha256 (&ctx_final_sha256, bdata, bytes);
        sph_sha256_close(&ctx_final_sha256, (void*)(hash));

        int digits=(int)((sqrt((double)(nnNonce2))*(1.+EPS))/9000+75);
        int iterations=20;
        mpf_set_default_prec((long int)(digits*BITS_PER_DIGIT+16));

        mpz_t magipi;
        mpz_t magisw;
        mpf_t magifpi;
        mpf_t mpa1, mpb1, mpt1, mpp1;
        mpf_t mpa2, mpb2, mpt2, mpp2;
        mpf_t mpsft;

        mpz_init(magipi);
        mpz_init(magisw);
        mpf_init(magifpi);
        mpf_init(mpsft);
        mpf_init(mpa1);
        mpf_init(mpb1);
        mpf_init(mpt1);
        mpf_init(mpp1);

        mpf_init(mpa2);
        mpf_init(mpb2);
        mpf_init(mpt2);
        mpf_init(mpp2);

        uint32_t usw_;
        usw_ = sw_(nnNonce2, SW_DIVS);
        if (usw_ < 1) usw_ = 1;
        mpz_set_ui(magisw, usw_);
        uint32_t mpzscale=mpz_size(magisw);

        for(int i=0; i < NM7M; i++){
            if (mpzscale > 1000) {
                mpzscale = 1000;
            }
            else if (mpzscale < 1) {
                mpzscale = 1;
            }

            mpf_set_ui(mpa1, 1);
            mpf_set_ui(mpb1, 2);
            mpf_set_d(mpt1, 0.25*mpzscale);
            mpf_set_ui(mpp1, 1);
            mpf_sqrt(mpb1, mpb1);
            mpf_ui_div(mpb1, 1, mpb1);
            mpf_set_ui(mpsft, 10);

            for(int j=0; j <= iterations; j++){
	            mpf_add(mpa2, mpa1,  mpb1);
            	mpf_div_ui(mpa2, mpa2, 2);
            	mpf_mul(mpb2, mpa1, mpb1);
            	mpf_abs(mpb2, mpb2);
            	mpf_sqrt(mpb2, mpb2);
            	mpf_sub(mpt2, mpa1, mpa2);
            	mpf_abs(mpt2, mpt2);
            	mpf_sqrt(mpt2, mpt2);
            	mpf_mul(mpt2, mpt2, mpp1);
            	mpf_sub(mpt2, mpt1, mpt2);
            	mpf_mul_ui(mpp2, mpp1, 2);
            	mpf_swap(mpa1, mpa2);
            	mpf_swap(mpb1, mpb2);
            	mpf_swap(mpt1, mpt2);
            	mpf_swap(mpp1, mpp2);
            }

            mpf_add(magifpi, mpa1, mpb1);
            mpf_pow_ui(magifpi, magifpi, 2);
            mpf_div_ui(magifpi, magifpi, 4);
            mpf_abs(mpt1, mpt1);
            mpf_div(magifpi, magifpi, mpt1);

            mpf_pow_ui(mpsft, mpsft, digits/2);
            mpf_mul(magifpi, magifpi, mpsft);

            mpz_set_f(magipi, magifpi);

            mpz_add(product,product,magipi);
            mpz_add(product,product,magisw);

            mpz_set_uint256(bns[0], (void*)(hash));
            mpz_add(bns[7], bns[7], bns[0]);

            mpz_mul(product,product,bns[7]);
            mpz_cdiv_q (product, product, bns[0]);
            if (mpz_sgn(product) <= 0) mpz_set_ui(product,1);

            bytes = mpz_sizeinbase(product, 256);
            mpzscale=bytes;
            bdata = (uint8_t *)realloc(bdata, bytes);
            mpz_export(bdata, NULL, -1, 1, 0, 0, product);

            sph_sha256_init(&ctx_final_sha256);
            sph_sha256 (&ctx_final_sha256, bdata, bytes);
            sph_sha256_close(&ctx_final_sha256, (void*)(hash));

        }

        mpz_clear(magipi);
        mpz_clear(magisw);
        mpf_clear(magifpi);
        mpf_clear(mpsft);
        mpf_clear(mpa1);
        mpf_clear(mpb1);
        mpf_clear(mpt1);
        mpf_clear(mpp1);

        mpf_clear(mpa2);
        mpf_clear(mpb2);
        mpf_clear(mpt2);
        mpf_clear(mpp2);

        rc = fulltest_m7hash(hash, ptarget);
        if (rc) {
            if (opt_debug) {
                bin2hex(hash_str, (unsigned char *)hash, 32);
                bin2hex(target_str, (unsigned char *)ptarget, 32);
                bin2hex(data_str, (unsigned char *)data, 80);
                applog(LOG_DEBUG, "DEBUG: [%d thread] Found share!\ndata   %s\nhash   %s\ntarget %s", thr_id, 
                    data_str,
                    hash_str,
                    target_str);
            }

            pdata[19] = data[19];

            goto out;
        }
    } while (n < max_nonce && !work_restart[thr_id].restart);

    pdata[19] = n;

out:
    for(int i=0; i < 8; i++){
        mpz_clear(bns[i]);
    }
    mpz_clear(product);
    free(bdata);

    *hashes_done = n - first_nonce + 1;
    return rc;
}
void init_myriadcoin_groestl_contexts(void *dummy)
{
	sph_groestl512_init(&ctx.groestl);
	sph_sha256_init(&ctx.sha2);
}
Beispiel #12
0
int scanhash_m7hash(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
    uint64_t max_nonce, unsigned long *hashes_done)
{
    uint32_t data[32] __attribute__((aligned(128)));
    uint32_t *data_p64 = data + (M7_MIDSTATE_LEN / sizeof(data[0]));
    uint32_t hash[8] __attribute__((aligned(32)));
    uint8_t bhash[7][64] __attribute__((aligned(32)));
    uint32_t hashtest[8] __attribute__((aligned(32)));
    uint32_t n = pdata[29] - 1;
    const uint32_t first_nonce = pdata[29];
    char data_str[245], hash_str[65], target_str[65];
    uint8_t *bdata = 0;
    mpz_t bns[7];
    int rc = 0;

    for(int i=0; i < 7; i++){
        mpz_init(bns[i]);
    }

    memcpy(data, pdata, 122);

    sph_sha256_context       ctx_final_sha256;

    sph_sha256_context       ctx_sha256;
    sph_sha512_context       ctx_sha512;
    sph_keccak512_context    ctx_keccak;
    sph_whirlpool_context    ctx_whirlpool;
    sph_haval256_5_context   ctx_haval;
    sph_tiger_context        ctx_tiger;
    sph_ripemd160_context    ctx_ripemd;

    sph_sha256_init(&ctx_sha256);
    sph_sha256 (&ctx_sha256, data, M7_MIDSTATE_LEN);
    
    sph_sha512_init(&ctx_sha512);
    sph_sha512 (&ctx_sha512, data, M7_MIDSTATE_LEN);
    
    sph_keccak512_init(&ctx_keccak);
    sph_keccak512 (&ctx_keccak, data, M7_MIDSTATE_LEN);

    sph_whirlpool_init(&ctx_whirlpool);
    sph_whirlpool (&ctx_whirlpool, data, M7_MIDSTATE_LEN);
    
    sph_haval256_5_init(&ctx_haval);
    sph_haval256_5 (&ctx_haval, data, M7_MIDSTATE_LEN);

    sph_tiger_init(&ctx_tiger);
    sph_tiger (&ctx_tiger, data, M7_MIDSTATE_LEN);

    sph_ripemd160_init(&ctx_ripemd);
    sph_ripemd160 (&ctx_ripemd, data, M7_MIDSTATE_LEN);

    sph_sha256_context       ctx2_sha256;
    sph_sha512_context       ctx2_sha512;
    sph_keccak512_context    ctx2_keccak;
    sph_whirlpool_context    ctx2_whirlpool;
    sph_haval256_5_context   ctx2_haval;
    sph_tiger_context        ctx2_tiger;
    sph_ripemd160_context    ctx2_ripemd;

    do {
        data[29] = ++n;

        memset(bhash, 0, 7 * 64);

        ctx2_sha256 = ctx_sha256;
        sph_sha256 (&ctx2_sha256, data_p64, 122 - M7_MIDSTATE_LEN);
        sph_sha256_close(&ctx2_sha256, (void*)(bhash[0]));

        ctx2_sha512 = ctx_sha512;
        sph_sha512 (&ctx2_sha512, data_p64, 122 - M7_MIDSTATE_LEN);
        sph_sha512_close(&ctx2_sha512, (void*)(bhash[1]));
        
        ctx2_keccak = ctx_keccak;
        sph_keccak512 (&ctx2_keccak, data_p64, 122 - M7_MIDSTATE_LEN);
        sph_keccak512_close(&ctx2_keccak, (void*)(bhash[2]));

        ctx2_whirlpool = ctx_whirlpool;
        sph_whirlpool (&ctx2_whirlpool, data_p64, 122 - M7_MIDSTATE_LEN);
        sph_whirlpool_close(&ctx2_whirlpool, (void*)(bhash[3]));
        
        ctx2_haval = ctx_haval;
        sph_haval256_5 (&ctx2_haval, data_p64, 122 - M7_MIDSTATE_LEN);
        sph_haval256_5_close(&ctx2_haval, (void*)(bhash[4]));

        ctx2_tiger = ctx_tiger;
        sph_tiger (&ctx2_tiger, data_p64, 122 - M7_MIDSTATE_LEN);
        sph_tiger_close(&ctx2_tiger, (void*)(bhash[5]));

        ctx2_ripemd = ctx_ripemd;
        sph_ripemd160 (&ctx2_ripemd, data_p64, 122 - M7_MIDSTATE_LEN);
        sph_ripemd160_close(&ctx2_ripemd, (void*)(bhash[6]));

        for(int i=0; i < 7; i++){
            set_one_if_zero(bhash[i]);
            mpz_set_uint512(bns[i],bhash[i]);
        }
        
        for(int i=6; i > 0; i--){
            mpz_mul(bns[i-1], bns[i-1], bns[i]);
        }

        int bytes = mpz_sizeinbase(bns[0], 256);
        bdata = (uint8_t *)realloc(bdata, bytes);
        mpz_export((void *)bdata, NULL, -1, 1, 0, 0, bns[0]);

        sph_sha256_init(&ctx_final_sha256);
        sph_sha256 (&ctx_final_sha256, bdata, bytes);
        sph_sha256_close(&ctx_final_sha256, (void*)(hash));

        rc = fulltest_m7hash(hash, ptarget);
        if (rc) {
            if (opt_debug) {
                bin2hex(hash_str, (unsigned char *)hash, 32);
                bin2hex(target_str, (unsigned char *)ptarget, 32);
                bin2hex(data_str, (unsigned char *)data, 122);
                applog(LOG_DEBUG, "DEBUG: [%d thread] Found share!\ndata   %s\nhash   %s\ntarget %s", thr_id, 
                    data_str,
                    hash_str,
                    target_str);
            }

            pdata[29] = data[29];

            goto out;
        }
    } while (n < max_nonce && !work_restart[thr_id].restart);

    pdata[29] = n;

out:
    for(int i=0; i < 7; i++){
        mpz_clear(bns[i]);
    }

    *hashes_done = n - first_nonce + 1;
    free(bdata);
    return rc;
}
Beispiel #13
0
//#define SW_MAX 1000
void m7magi_hash(const char* input, char* output)
{
    unsigned int nnNonce;
    uint32_t pdata[32];
    memcpy(pdata, input, 80);
//    memcpy(&nnNonce, input+76, 4);

    int i, j, bytes, nnNonce2;
    nnNonce2 = (int)(pdata[19]/2);
    size_t sz = 80;
    uint8_t bhash[7][64];
    uint32_t hash[8];
    memset(bhash, 0, 7 * 64);

    sph_sha256_context       ctx_final_sha256;

    sph_sha256_context       ctx_sha256;
    sph_sha512_context       ctx_sha512;
    sph_keccak512_context    ctx_keccak;
    sph_whirlpool_context    ctx_whirlpool;
    sph_haval256_5_context   ctx_haval;
    sph_tiger_context        ctx_tiger;
    sph_ripemd160_context    ctx_ripemd;

    sph_sha256_init(&ctx_sha256);
    // ZSHA256;
    sph_sha256 (&ctx_sha256, input, sz);
    sph_sha256_close(&ctx_sha256, (void*)(bhash[0]));

    sph_sha512_init(&ctx_sha512);
    // ZSHA512;
    sph_sha512 (&ctx_sha512, input, sz);
    sph_sha512_close(&ctx_sha512, (void*)(bhash[1]));
    
    sph_keccak512_init(&ctx_keccak);
    // ZKECCAK;
    sph_keccak512 (&ctx_keccak, input, sz);
    sph_keccak512_close(&ctx_keccak, (void*)(bhash[2]));

    sph_whirlpool_init(&ctx_whirlpool);
    // ZWHIRLPOOL;
    sph_whirlpool (&ctx_whirlpool, input, sz);
    sph_whirlpool_close(&ctx_whirlpool, (void*)(bhash[3]));
    
    sph_haval256_5_init(&ctx_haval);
    // ZHAVAL;
    sph_haval256_5 (&ctx_haval, input, sz);
    sph_haval256_5_close(&ctx_haval, (void*)(bhash[4]));

    sph_tiger_init(&ctx_tiger);
    // ZTIGER;
    sph_tiger (&ctx_tiger, input, sz);
    sph_tiger_close(&ctx_tiger, (void*)(bhash[5]));

    sph_ripemd160_init(&ctx_ripemd);
    // ZRIPEMD;
    sph_ripemd160 (&ctx_ripemd, input, sz);
    sph_ripemd160_close(&ctx_ripemd, (void*)(bhash[6]));

//    printf("%s\n", hash[6].GetHex().c_str());

    mpz_t bns[8];
    for(i=0; i < 8; i++){
        mpz_init(bns[i]);
    }
    //Take care of zeros and load gmp
    for(i=0; i < 7; i++){
	set_one_if_zero(bhash[i]);
	mpz_set_uint512(bns[i],bhash[i]);
    }

    mpz_set_ui(bns[7],0);
    for(i=0; i < 7; i++)
	mpz_add(bns[7], bns[7], bns[i]);

    mpz_t product;
    mpz_init(product);
    mpz_set_ui(product,1);
//    mpz_pow_ui(bns[7], bns[7], 2);
    for(i=0; i < 8; i++){
	mpz_mul(product,product,bns[i]);
    }
    mpz_pow_ui(product, product, 2);

    bytes = mpz_sizeinbase(product, 256);
//    printf("M7M data space: %iB\n", bytes);
    char *data = (char*)malloc(bytes);
    mpz_export(data, NULL, -1, 1, 0, 0, product);

    sph_sha256_init(&ctx_final_sha256);
    // ZSHA256;
    sph_sha256 (&ctx_final_sha256, data, bytes);
    sph_sha256_close(&ctx_final_sha256, (void*)(hash));
    free(data);

    int digits=(int)((sqrt((double)(nnNonce2))*(1.+EPS))/9000+75);
//    int iterations=(int)((sqrt((double)(nnNonce2))+EPS)/500+350); // <= 500
//    int digits=100;
    int iterations=20; // <= 500
    mpf_set_default_prec((long int)(digits*BITS_PER_DIGIT+16));

    mpz_t magipi;
    mpz_t magisw;
    mpf_t magifpi;
    mpf_t mpa1, mpb1, mpt1, mpp1;
    mpf_t mpa2, mpb2, mpt2, mpp2;
    mpf_t mpsft;

    mpz_init(magipi);
    mpz_init(magisw);
    mpf_init(magifpi);
    mpf_init(mpsft);
    mpf_init(mpa1);
    mpf_init(mpb1);
    mpf_init(mpt1);
    mpf_init(mpp1);

    mpf_init(mpa2);
    mpf_init(mpb2);
    mpf_init(mpt2);
    mpf_init(mpp2);

    uint32_t usw_;
    usw_ = sw_(nnNonce2, SW_DIVS);
    if (usw_ < 1) usw_ = 1;
//    if(fDebugMagi) printf("usw_: %d\n", usw_);
    mpz_set_ui(magisw, usw_);
    uint32_t mpzscale=mpz_size(magisw);
for(i=0; i < NM7M; i++)
{
    if (mpzscale > 1000) {
      mpzscale = 1000;
    }
    else if (mpzscale < 1) {
      mpzscale = 1;
    }
//    if(fDebugMagi) printf("mpzscale: %d\n", mpzscale);

    mpf_set_ui(mpa1, 1);
    mpf_set_ui(mpb1, 2);
    mpf_set_d(mpt1, 0.25*mpzscale);
    mpf_set_ui(mpp1, 1);
    mpf_sqrt(mpb1, mpb1);
    mpf_ui_div(mpb1, 1, mpb1);
    mpf_set_ui(mpsft, 10);

    for(j=0; j <= iterations; j++)
    {
	mpf_add(mpa2, mpa1,  mpb1);
	mpf_div_ui(mpa2, mpa2, 2);
	mpf_mul(mpb2, mpa1, mpb1);
	mpf_abs(mpb2, mpb2);
	mpf_sqrt(mpb2, mpb2);
	mpf_sub(mpt2, mpa1, mpa2);
	mpf_abs(mpt2, mpt2);
	mpf_sqrt(mpt2, mpt2);
	mpf_mul(mpt2, mpt2, mpp1);
	mpf_sub(mpt2, mpt1, mpt2);
	mpf_mul_ui(mpp2, mpp1, 2);
	mpf_swap(mpa1, mpa2);
	mpf_swap(mpb1, mpb2);
	mpf_swap(mpt1, mpt2);
	mpf_swap(mpp1, mpp2);
    }
    mpf_add(magifpi, mpa1, mpb1);
    mpf_pow_ui(magifpi, magifpi, 2);
    mpf_div_ui(magifpi, magifpi, 4);
    mpf_abs(mpt1, mpt1);
    mpf_div(magifpi, magifpi, mpt1);

//    mpf_out_str(stdout, 10, digits+2, magifpi);

    mpf_pow_ui(mpsft, mpsft, digits/2);
    mpf_mul(magifpi, magifpi, mpsft);

    mpz_set_f(magipi, magifpi);

//mpz_set_ui(magipi,1);

    mpz_add(product,product,magipi);
    mpz_add(product,product,magisw);
    
    mpz_set_uint256(bns[0], (void*)(hash));
    mpz_add(bns[7], bns[7], bns[0]);

    mpz_mul(product,product,bns[7]);
    mpz_cdiv_q (product, product, bns[0]);
    if (mpz_sgn(product) <= 0) mpz_set_ui(product,1);

    bytes = mpz_sizeinbase(product, 256);
    mpzscale=bytes;
//    printf("M7M data space: %iB\n", bytes);
    char *bdata = (char*)malloc(bytes);
    mpz_export(bdata, NULL, -1, 1, 0, 0, product);

    sph_sha256_init(&ctx_final_sha256);
    // ZSHA256;
    sph_sha256 (&ctx_final_sha256, bdata, bytes);
    sph_sha256_close(&ctx_final_sha256, (void*)(hash));
    free(bdata);
}
    //Free the memory
    for(i=0; i < 8; i++){
	mpz_clear(bns[i]);
    }
//    mpz_clear(dSpectralWeight);
    mpz_clear(product);

    mpz_clear(magipi);
    mpz_clear(magisw);
    mpf_clear(magifpi);
    mpf_clear(mpsft);
    mpf_clear(mpa1);
    mpf_clear(mpb1);
    mpf_clear(mpt1);
    mpf_clear(mpp1);

    mpf_clear(mpa2);
    mpf_clear(mpb2);
    mpf_clear(mpt2);
    mpf_clear(mpp2);
    
    memcpy(output, hash, 32);
}