void operator()(std::map<uint64_t, uint64_t> &accounts, std::string thread_seed) { // Our approach is to pick a random point and repeatedly double it. // This is cheaper than the more naive approach of multiplying the // generator point times random exponents. // We work in batches because our point doubling algorithm requires a // modular inversion which is more efficiently computed in batches. const int n = BATCH_SIZE; felem xs[BATCH_SIZE], zs[BATCH_SIZE]; std::vector<bytestring> exponents; static const unsigned char generator[32] = {9}; for ( int i = 0; i < n; i++ ) { bytestring exponent(32, 0); std::string exponent_seed = boost::str(boost::format("%1%:%2%") % thread_seed % i); sha256((unsigned char*) &exponent_seed[0], exponent_seed.size(), &exponent[0]); // transform initial exponent according to curve25519 tweaks exponent[0] &= 248; exponent[31] &= 127; exponent[31] |= 64; uint8_t pubkey[32]; curve25519_donna(pubkey, &exponent[0], generator); fexpand(xs[i], pubkey); exponents.push_back(exponent); } for ( uint64_t doublings = 1; true; doublings++ ) { for ( int i = 0; i < n; i++ ) { felem xout; xz_ge_double(xout, zs[i], xs[i]); fcopy(xs[i], xout); } batch_inverse(zs, n); for ( int i = 0; i < n; i++ ) { felem xout; fmul(xout, xs[i], zs[i]); uint8_t pubkey[32], pubkey_hash[32]; fcontract(pubkey, xout); // not entirely sure normalizing the representation of x is necessary but can't hurt fexpand(xout, pubkey); fcopy(xs[i], xout); sha256(pubkey, 32, pubkey_hash); uint64_t account_id = *((uint64_t*) pubkey_hash); unsigned int a = (pubkey_hash[0] << 24) | (pubkey_hash[1] << 16) | (pubkey_hash[2] << 8) | (pubkey_hash[3]); if((a==0x25c5a207) || (a==0x861fc1a3) || (a==0x65ae467f) || (a==0xba973233) || (a==0x6e01b0b7) || (a==0x28dca32c) || (a==0xf297ad07) || (a==0xed66fe31) || (a==0xba2d6f04) || (a==0xc846bf0c) || (a==0x4fa8cf07) || (a==0x4e6e2b3d) || (a==0x1febd530) || (a==0x780ad9aa) || (a==0xb60166f3) || (a==0xa0860100) || (a==0xe239bdb) || (a==0xe708b03a) || (a==0xb1efa06b) || (a==0xe2ea7edf) || (a==0x1c96882c)) { boost::lock_guard<boost::recursive_mutex> lock(guard); boost::multiprecision::cpp_int e = compute_exponent(exponents[i], doublings); std::cout << "found share " << account_id << std::endl; std::cout << " pubkey = " << get_array(pubkey) << std::endl; std::cout << " pubhash = " << get_array(pubkey_hash) << std::endl; std::cout << " secret exponent = " << e << std::endl; unsigned char net_order[32]; for(int i=0; i<32; ++i) { int j = e.convert_to<int>(); net_order[31-i] = j & 0xFF; e = e >> 8; } submit_share(account,get_array(net_order)); } } checked += n; }
/** * test the found candidates with the fermat primality test */ static inline void test_candidates(Sieve *const sieve, const sieve_t *const cc1, const sieve_t *const twn, const sieve_t *const all, const mpz_t mpz_primorial, const uint32_t extension) { SieveStats *const stats = &sieve->stats; TestParams *const test_params = &sieve->test_params; uint32_t i; for (i = (use_first_half ? 0 : sieve_words / 2); sieve->active && i < sieve_words; i++) { /* current word */ const sieve_t word = all[i]; /* skip a word if there are no candidates in it */ if (word == word_max) continue; sieve_t n, bit; for (n = 1, bit = 0; n != 0; n <<= 1, bit++) { /* fond an not sieved index */ if ((word & n) == 0) { stats->tests++; /* break if sieve should terminate */ if (!sieve->active) break; /* origin = (primorial * index) * 2^extension */ mpz_mul_ui(sieve->mpz_test_origin, mpz_primorial, (word_bits * i + bit) << extension); uint32_t chain_length; char type; /* bi-twin candidate */ if ((twn[i] & n) == 0) { chain_length = twn_chain_test(sieve->mpz_test_origin, test_params); stats->twn[chain_length]++; type = BI_TWIN_CHAIN; /* cc1 candidate */ } else if ((cc1[i] & n) == 0) { chain_length = cc1_chain_test(sieve->mpz_test_origin, test_params); stats->cc1[chain_length]++; type = FIRST_CUNNINGHAM_CHAIN; /* cc2 candidate */ } else { chain_length = cc2_chain_test(sieve->mpz_test_origin, test_params); stats->cc2[chain_length]++; type = SECOND_CUNNINGHAM_CHAIN; } if (chain_length >= pool_share) { /* calculate the difficulty */ uint32_t difficulty = chain_length << FRACTIONAL_BITS; difficulty += get_fractional_length(sieve->mpz_test_origin, type, chain_length, &sieve->test_params); /* calculate the proove of work certificate */ mpz_mul_ui(sieve->mpz_multiplier, mpz_fixed_hash_multiplier, (word_bits * i + bit) << extension); size_t multiplier_length; memset(sieve->header.primemultiplier, 0, MULTIPLIER_LENGTH); mpz_to_ary(sieve->mpz_multiplier, sieve->header.primemultiplier, &multiplier_length); if (multiplier_length > MULTIPLIER_LENGTH) { error_msg("[EE] to less space for primemultiplier\n"); continue; } sieve->header.multiplier_length = (uint8_t) multiplier_length; /* check share if debuging is enabled */ check_share(&sieve->header, difficulty, type); submit_share(&sieve->header, type, difficulty); } } } } }