Bitcoin Forum
May 08, 2024, 06:23:36 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: « 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 [47] 48 49 50 51 52 53 54 55 56 57 58 59 60 61 »
  Print  
Author Topic: VanitySearch (Yet another address prefix finder)  (Read 31274 times)
NotATether
Legendary
*
Offline Offline

Activity: 1596
Merit: 6730


bitcoincleanup.com / bitmixlist.org


View Profile WWW
March 11, 2021, 04:16:18 AM
 #921

Code:
GPUEngine: Launch: an illegal memory access was encountered

if i tray to create a single adress / key pair it works realy fast on my 3070 card, but from a input list with only 20 full adresses, the illegal memory access pops up.
~snip
The problem, if I remember correctly, is the RIPEMD160 function when trying to do more than one address. So, you need to create the string function; meaning, take off like 7 or 8 characters on your addresses in your list and see if that works.

Example:
turn address:
139743984739847328974982472347398
into
1397439847398473289749824

I do not know if it works with the latest release of VanitySearch but I know it works with version 17.

Illegal memory accesses in VanitySearch too? Damn I wish that the names of functions were printed to standard output as a habit. (Bitcrack and Kangaroo are guilty of this non-practice too.) Errors like this make it hard for me to find the source, although according to you the buggy code is somewhere in a RIPEMD160 function.

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
1715192616
Hero Member
*
Offline Offline

Posts: 1715192616

View Profile Personal Message (Offline)

Ignore
1715192616
Reply with quote  #2

1715192616
Report to moderator
1715192616
Hero Member
*
Offline Offline

Posts: 1715192616

View Profile Personal Message (Offline)

Ignore
1715192616
Reply with quote  #2

1715192616
Report to moderator
1715192616
Hero Member
*
Offline Offline

Posts: 1715192616

View Profile Personal Message (Offline)

Ignore
1715192616
Reply with quote  #2

1715192616
Report to moderator
"In a nutshell, the network works like a distributed timestamp server, stamping the first transaction to spend a coin. It takes advantage of the nature of information being easy to spread but hard to stifle." -- Satoshi
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
WanderingPhilospher
Full Member
***
Offline Offline

Activity: 1064
Merit: 219

Shooters Shoot...


View Profile
March 11, 2021, 05:55:24 AM
 #922

Quote
Illegal memory accesses in VanitySearch too? Damn I wish that the names of functions were printed to standard output as a habit. (Bitcrack and Kangaroo are guilty of this non-practice too.) Errors like this make it hard for me to find the source, although according to you the buggy code is somewhere in a RIPEMD160 function.
Yes, like I said, version 17 works with the string function (taking off last 7 or 8 characters) for the 30xx series cards but will not work with full address. Also, I don't think the newest version works with string with the 30xx cards. I think that's why I went back to version 17.  (No particular reason, I already had it compiled and tweaked so I just keep on using it, version 17 that is) I'm not 100 percent (because I have ran a lot of programs on different cards, but I don't think the newest version will run full address with latest drivers. It's a mess; I'll have to keep better notes.

So yeah, bitcrack absolutely doesn't work with 30xx, VS does but with string option, Kangaroo works fine but it is not optimized for 30xx cards; it doesn't take full advantage of the horsepower under the hood.

A side note, for those of you who do have a 30xx card, to get the program to actually read the sm cores correctly, add:

Code:
{0x86,  128},

to the GPUEngine.cu like this:
Code:
sSMtoCores nGpuArchCoresPerSM[] = {
      {0x20, 32}, // Fermi Generation (SM 2.0) GF100 class
      {0x21, 48}, // Fermi Generation (SM 2.1) GF10x class
      {0x30, 192},
      {0x32, 192},
      {0x35, 192},
      {0x37, 192},
      {0x50, 128},
      {0x52, 128},
      {0x53, 128},
      {0x60,  64},
      {0x61, 128},
      {0x62, 128},
      {0x70,  64},
      {0x72,  64},
      {0x75,  64},
      {0x86,  128},
      {-1, -1} };
Atariko
Newbie
*
Offline Offline

Activity: 12
Merit: 0


View Profile
March 11, 2021, 06:35:36 PM
 #923

I have videocard MSI 2070 Super and the same problem, version 17 works and newer ones do not. I previously wrote about this problem on page 39. I'm also really looking forward to a solution to the problem
WanderingPhilospher
Full Member
***
Offline Offline

Activity: 1064
Merit: 219

Shooters Shoot...


View Profile
March 11, 2021, 06:55:24 PM
 #924

I have videocard MSI 2070 Super and the same problem, version 17 works and newer ones do not. I previously wrote about this problem on page 39. I'm also really looking forward to a solution to the problem
You said:

Quote
P.S.  VanitySearch119.exe -r 1000000 -t 4 -g 320,256 -o found.txt -i 500.txt   This configuration works without problems.

So you finally got VS 19 to work with over 50 addresses? I'm assuming the -i 500.txt meant 500 addresses?
Atariko
Newbie
*
Offline Offline

Activity: 12
Merit: 0


View Profile
March 12, 2021, 04:53:37 PM
 #925

I have videocard MSI 2070 Super and the same problem, version 17 works and newer ones do not. I previously wrote about this problem on page 39. I'm also really looking forward to a solution to the problem
You said:

Quote
P.S.  VanitySearch119.exe -r 1000000 -t 4 -g 320,256 -o found.txt -i 500.txt   This configuration works without problems.

So you finally got VS 19 to work with over 50 addresses? I'm assuming the -i 500.txt meant 500 addresses?

I corrected that post. (only works if i-<50 full addresses) But version 117 works with any number of addresses
bery89
Newbie
*
Offline Offline

Activity: 7
Merit: 0


View Profile
March 13, 2021, 09:34:22 AM
 #926

hi,

having trouble to run on gpu. keep show:
GPUEngine: CudaGetDeviceCount CUDA driver version is insufficient for CUDA runtime version 35

what can i do to make gpu run?
cpu working just fine.

i just try
fresh install win 10 64B build 19042
install cuda 8 and cuda 10

bat file:
VanitySearch.exe -o key.txt 1Try
version 1.19

specs
intel i3
gtx 750

thanks in advance

NotATether
Legendary
*
Offline Offline

Activity: 1596
Merit: 6730


bitcoincleanup.com / bitmixlist.org


View Profile WWW
March 14, 2021, 04:26:57 AM
 #927

having trouble to run on gpu. keep show:
GPUEngine: CudaGetDeviceCount CUDA driver version is insufficient for CUDA runtime version 35

You need to update your NVIDIA drivers, the latest ones (460.xx) support Kepler GPUs and should do the job.

Keep in mind that the CUDA version and NVIDIA driver version are independent from each other, such that it's possible to have a broken configuration where you have a modern CUDA toolkit installed and it compiles successfully, but crashes at runtime because the driver cannot load CUDA 3.5 kernels.

A side note, for those of you who do have a 30xx card, to get the program to actually read the sm cores correctly, add:

Code:
{0x86,  128},

to the GPUEngine.cu

I recall the Ampere tuning guide saying there are 64 warps per SM for 8.0 (Quadro A100 I believe) and 8.6 Ampere.

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
WanderingPhilospher
Full Member
***
Offline Offline

Activity: 1064
Merit: 219

Shooters Shoot...


View Profile
March 14, 2021, 04:35:48 AM
 #928

Quote
I recall the Ampere tuning guide saying there are 64 warps per SM for 8.0 (Quadro A100 I believe) and 8.6 Ampere.
they have dual so 2 x 64...that's what I read.
LaryKing
Newbie
*
Offline Offline

Activity: 1
Merit: 0


View Profile
March 14, 2021, 09:31:41 AM
 #929

Hello, tell me pls, did anyone manage to solve the problem with the GPU Engine: Launch: an illegal memory access was encountered?
GTX 1660 super, ccap 75, cuda 11.1-11.2, driver 460

At one specific address, it starts - example - ./VanitySearch -gpu -r 888800 -m 2550000 -o results.txt 187a4nvtULDNS2K17NPu67nGZgHjiJEtz9
But with the list of addresses, there is already a problem - example (trying different variation to start (./VanitySearch -gpu -i list.txt for example))

Code:
./VanitySearch -gpu -i list.txt
VanitySearch v1.19
Search: 219 addresses (Lookup size 160,[1,4]) [Compressed]
Start Sun Mar 14 12:31:18 2021
Base Key: D494AFF76C68AD751A746BC5BF78B0C7286EA8EBFB29EDC248D07F00DBFB2928
Number of CPU thread: 1
GPU: GPU #0 GeForce GTX 1660 SUPER (22x64 cores) Grid(176x128)
GPUEngine: Launch: an illegal memory access was encountered
WhyFhy
Hero Member
*****
Offline Offline

Activity: 1430
Merit: 513



View Profile
March 14, 2021, 04:04:42 PM
 #930

hi,

having trouble to run on gpu. keep show:
GPUEngine: CudaGetDeviceCount CUDA driver version is insufficient for CUDA runtime version 35

what can i do to make gpu run?
cpu working just fine.

i just try
fresh install win 10 64B build 19042
install cuda 8 and cuda 10

bat file:
VanitySearch.exe -o key.txt 1Try
version 1.19

specs
intel i3
gtx 750

thanks in advance



Old card requires older cuda (5 or 6) try 334 drivers

  BTC
.
BTC
.
 BTC
.
BTC
/]..[banned mixer]..
██
██
██
██
██
██
██

██

██

██

██
/]YOUR OPPORTUNITY TO
HAVE BITCOIN BUSINESS

██
██
██
██
██
██
██

██

██

██

██
.
  BTC
. BTC
.
.
 
BTC
  BTC
Dr88
Newbie
*
Offline Offline

Activity: 15
Merit: 0


View Profile
March 14, 2021, 06:00:29 PM
 #931

hi i want to generate 64 bit not full 256 now i change "keys.Rand(256);" to "keys.Rand(64);" on VanitySearch::getGPUStartingKeys but only some keys are  64 bit what i am missing i am new on c++
WanderingPhilospher
Full Member
***
Offline Offline

Activity: 1064
Merit: 219

Shooters Shoot...


View Profile
March 14, 2021, 06:12:52 PM
 #932

hi i want to generate 64 bit not full 256 now i change "keys.Rand(256);" to "keys.Rand(64);" on VanitySearch::getGPUStartingKeys but only some keys are  64 bit what i am missing i am new on c++
most of keys found will be outside of 64 bit due to the endo and symm. Basically the program takes in inputted key, say 64 bit, but then checks it and 5 other keys related to that 64 bit key. So you would have to comment out those sections if you want all keys in the 64 bit range.
Dr88
Newbie
*
Offline Offline

Activity: 15
Merit: 0


View Profile
March 14, 2021, 06:40:10 PM
Last edit: March 14, 2021, 07:16:23 PM by Dr88
 #933

hi i want to generate 64 bit not full 256 now i change "keys.Rand(256);" to "keys.Rand(64);" on VanitySearch::getGPUStartingKeys but only some keys are  64 bit what i am missing i am new on c++
most of keys found will be outside of 64 bit due to the endo and symm. Basically the program takes in inputted key, say 64 bit, but then checks it and 5 other keys related to that 64 bit key. So you would have to comment out those sections if you want all keys in the 64 bit range.
can you help me which code section need i comment
Code:
/*
 * This file is part of the VanitySearch distribution (https://github.com/JeanLucPons/VanitySearch).
 * Copyright (c) 2019 Jean Luc PONS.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "Vanity.h"
#include "Base58.h"
#include "Bech32.h"
#include "hash/sha256.h"
#include "hash/sha512.h"
#include "IntGroup.h"
#include "Timer.h"
#include "hash/ripemd160.h"
#include <string.h>
#include <math.h>
#include <algorithm>
#ifndef WIN64
#include <pthread.h>
#endif

using namespace std;

Point Gn[CPU_GRP_SIZE / 2];
Point _2Gn;

// ----------------------------------------------------------------------------

VanitySearch::VanitySearch(Secp256K1 *secp, vector<std::string> &inputPrefixes,string seed,int searchMode,
                           bool useGpu, bool stop, string outputFile, bool useSSE, uint32_t maxFound,
                           uint64_t rekey, Point &startPubKey) {

  this->secp = secp;
  this->searchMode = searchMode;
  this->useGpu = useGpu;
  this->stopWhenFound = stop;
  this->outputFile = outputFile;
  this->useSSE = useSSE;
  this->nbGPUThread = 0;
  this->maxFound = maxFound;
  this->rekey = rekey;
  this->searchType = -1;
  this->startPubKey = startPubKey;
  this->startPubKeySpecified = !startPubKey.isZero();

  lastRekey = 0;
  prefixes.clear();

  // Create a 65536 items lookup table
  PREFIX_TABLE_ITEM t;
  t.found = true;
  t.items = NULL;
  for(int i=0;i<65536;i++)
    prefixes.push_back(t);

  // Insert prefixes
  bool loadingProgress = (inputPrefixes.size()>1000);
  if(loadingProgress)
    printf("[Building lookup16   0.0%%]\r");

  nbPrefix = 0;
  onlyFull = true;
  for (int i = 0; i < (int)inputPrefixes.size(); i++) {
    PREFIX_ITEM it;
    if (initPrefix(inputPrefixes[i], &it)) {
      std::vector<PREFIX_ITEM> *items;
      items = prefixes[it.sPrefix].items;
      if (items == NULL) {
        prefixes[it.sPrefix].items = new vector<PREFIX_ITEM>();
        prefixes[it.sPrefix].found = false;
        items = prefixes[it.sPrefix].items;
        usedPrefix.push_back(it.sPrefix);
      }
      items->push_back(it);
      onlyFull &= it.isFull;
      nbPrefix++;
    }
    if(loadingProgress && i%1000==0)
      printf("[Building lookup16 %5.1f%%]\r",(((double)i)/(double)(inputPrefixes.size()-1)) * 100.0);
  }

  if (loadingProgress)
    printf("\n");

  //dumpPrefixes();

  if (nbPrefix == 0) {
    printf("VanitySearch: nothing to search !\n");
    exit(1);
  }

  // Second level lookup
  uint32_t unique_sPrefix = 0;
  uint32_t minI = 0xFFFFFFFF;
  uint32_t maxI = 0;
  for (int i = 0; i < prefixes.size(); i++) {
    std::vector<PREFIX_ITEM> *items;
    items = prefixes[i].items;
    if (items) {
      LPREFIX lit;
      lit.sPrefix = i;
      for (int j = 0; j < items->size(); j++)
        lit.lPrefixes.push_back((*items)[j].lPrefix);
      sort(lit.lPrefixes.begin(), lit.lPrefixes.end());
      usedPrefixL.push_back(lit);
      if( (uint32_t)lit.lPrefixes.size()>maxI ) maxI = (uint32_t)lit.lPrefixes.size();
      if( (uint32_t)lit.lPrefixes.size()<minI ) minI = (uint32_t)lit.lPrefixes.size();
      unique_sPrefix++;
    }
    if (loadingProgress)
      printf("[Building lookup32 %.1f%%]\r", ((double)i*100.0) / (double)prefixes.size());
  }

  if (loadingProgress)
    printf("\n");

  _difficulty = getDiffuclty();
  string seachInfo = string(searchModes[searchMode]) + (startPubKeySpecified?" With Public Key":"");
  if (nbPrefix == 1) {
    prefix_t p0 = usedPrefix[0];
    printf("Difficulty: %.0f\n", _difficulty);
    printf("Search: %s [%s]\n", (*prefixes[p0].items)[0].prefix, seachInfo.c_str());
  } else {
    if (onlyFull) {
      printf("Search: %d addresses (Lookup size %d,[%d,%d]) [%s]\n", nbPrefix, unique_sPrefix, minI, maxI, seachInfo.c_str());
    } else {
      printf("Search: %d prefixes (Lookup size %d) [%s]\n", nbPrefix, unique_sPrefix, seachInfo.c_str());
    }
  }

  // Compute Generator table G[n] = (n+1)*G

  Point g = secp->G;
  Gn[0] = g;
  g = secp->DoubleDirect(g);
  Gn[1] = g;
  for (int i = 2; i < CPU_GRP_SIZE/2; i++) {
    g = secp->AddDirect(g,secp->G);
    Gn[i] = g;
  }
  // _2Gn = CPU_GRP_SIZE*G
  _2Gn = secp->DoubleDirect(Gn[CPU_GRP_SIZE/2-1]);

  // Constant for endomorphism
  // if a is a nth primitive root of unity, a^-1 is also a nth primitive root.
  // beta^3 = 1 mod p implies also beta^2 = beta^-1 mop (by multiplying both side by beta^-1)
  // (beta^3 = 1 mod p),  beta2 = beta^-1 = beta^2
  // (lambda^3 = 1 mod n), lamba2 = lamba^-1 = lamba^2
  beta.SetBase16("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee");
  lambda.SetBase16("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72");
  beta2.SetBase16("851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40");
  lambda2.SetBase16("ac9c52b33fa3cf1f5ad9e3fd77ed9ba4a880b9fc8ec739c2e0cfc810b51283ce");

  // Seed
  if (seed.length() == 0) {
    // Default seed
    seed = to_string(Timer::getSeedFromTimer());
  }

  // Protect seed against "seed search attack" using pbkdf2_hmac_sha512
  string salt = "VanitySearch";
  unsigned char hseed[64];
  pbkdf2_hmac_sha512(hseed, 64, (const uint8_t *)seed.c_str(), seed.length(),
    (const uint8_t *)salt.c_str(), salt.length(),
    2048);
  startKey.SetInt32(0);
  sha256(hseed, 64, (unsigned char *)startKey.bits64);

  char *ctimeBuff;
  time_t now = time(NULL);
  ctimeBuff = ctime(&now);
  printf("Start %s", ctimeBuff);
  
  startKey.Rand(64);
  
  if (rekey > 0) {
    printf("Base Key: Randomly changed every %.0f Mkeys\n",(double)rekey);
    printf("Base Key: %s\n", startKey.GetBase16().c_str());
  } else {
    printf("Base Key: %s\n", startKey.GetBase16().c_str());
  }

}

// ----------------------------------------------------------------------------

bool VanitySearch::isSingularPrefix(std::string pref) {

  // check is the given prefix contains only 1
  bool only1 = true;
  int i=0;
  while (only1 && i < (int)pref.length()) {
    only1 = pref.data()[i] == '1';
    i++;
  }
  return only1;

}

// ----------------------------------------------------------------------------
bool VanitySearch::initPrefix(std::string &prefix,PREFIX_ITEM *it) {

  std::vector<unsigned char> result;
  string dummy1 = prefix;
  int nbDigit = 0;
  bool wrong = false;

  if (prefix.length() < 2) {
    printf("Ignoring prefix \"%s\" (too short)\n",prefix.c_str());
    return false;
  }

  int aType = -1;
  

  switch (prefix.data()[0]) {
  case '1':
    aType = P2PKH;
    break;
  case '3':
    aType = P2SH;
    break;
  case 'b':
  case 'B':
    std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::tolower);
    if(strncmp(prefix.c_str(), "bc1q", 4) == 0)
      aType = BECH32;
    break;
  }

  if (aType==-1) {
    printf("Ignoring prefix \"%s\" (must start with 1 or 3 or bc1q)\n", prefix.c_str());
    return false;
  }

  if (searchType == -1) searchType = aType;
  if (aType != searchType) {
    printf("Ignoring prefix \"%s\" (P2PKH, P2SH or BECH32 allowed at once)\n", prefix.c_str());
    return false;
  }

  if (aType == BECH32) {

    // BECH32
    uint8_t witprog[40];
    size_t witprog_len;
    int witver;
    const char* hrp = "bc";

    int ret = segwit_addr_decode(&witver, witprog, &witprog_len, hrp, prefix.c_str());

    // Try to attack a full address ?
    if (ret && witprog_len==20) {

      // mamma mia !
      it->difficulty = pow(2, 160);
      it->isFull = true;
      memcpy(it->hash160, witprog, 20);
      it->sPrefix = *(prefix_t *)(it->hash160);
      it->lPrefix = *(prefixl_t *)(it->hash160);
      it->prefix = (char *)prefix.c_str();
      it->prefixLength = (int)prefix.length();
      it->found = false;
      return true;

    }

    if (prefix.length() < 5) {
      printf("Ignoring prefix \"%s\" (too short, length<5 )\n", prefix.c_str());
      return false;
    }

    if (prefix.length() >= 36) {
      printf("Ignoring prefix \"%s\" (too long, length>36 )\n", prefix.c_str());
      return false;
    }

    uint8_t data[64];
    memset(data,0,64);
    size_t data_length;
    if(!bech32_decode_nocheck(data,&data_length,prefix.c_str()+4)) {
      printf("Ignoring prefix \"%s\" (Only \"023456789acdefghjklmnpqrstuvwxyz\" allowed)\n", prefix.c_str());
      return false;
    }

    // Difficulty
    it->sPrefix = *(prefix_t *)data;
    it->difficulty = pow(2, 5*(prefix.length()-4));
    it->isFull = false;
    it->lPrefix = 0;
    it->prefix = (char *)prefix.c_str();
    it->prefixLength = (int)prefix.length();
    it->found = false;

    return true;

  } else {

    // P2PKH/P2SH

    wrong = !DecodeBase58(prefix, result);

    if (wrong) {
      printf("Ignoring prefix \"%s\" (0, I, O and l not allowed)\n", prefix.c_str());
      return false;
    }

    // Try to attack a full address ?
    if (result.size() > 21) {

      // mamma mia !
      //if (!secp.CheckPudAddress(prefix)) {
      //  printf("Warning, \"%s\" (address checksum may never match)\n", prefix.c_str());
      //}
      it->difficulty = pow(2, 160);
      it->isFull = true;
      memcpy(it->hash160, result.data() + 1, 20);
      it->sPrefix = *(prefix_t *)(it->hash160);
      it->lPrefix = *(prefixl_t *)(it->hash160);
      it->prefix = (char *)prefix.c_str();
      it->prefixLength = (int)prefix.length();
      it->found = false;
      return true;

    }

    // Prefix containing only '1'
    if (isSingularPrefix(prefix)) {

      if (prefix.length() > 21) {
        printf("Ignoring prefix \"%s\" (Too much 1)\n", prefix.c_str());
        return false;
      }

      // Difficulty
      it->difficulty = pow(256, prefix.length() - 1);
      it->isFull = false;
      it->sPrefix = 0;
      it->lPrefix = 0;
      it->prefix = (char *)prefix.c_str();
      it->prefixLength = (int)prefix.length();
      it->found = false;
      return true;

    }

    // Search for highest hash160 16bit prefix (most probable)

    while (result.size() < 25) {
      DecodeBase58(dummy1, result);
      if (result.size() < 25) {
        dummy1.append("1");
        nbDigit++;
      }
    }

    if (searchType == P2SH) {
      if (result.data()[0] != 5) {
        printf("Ignoring prefix \"%s\" (Unreachable, 31h1 to 3R2c only)\n", prefix.c_str());
        return false;
      }
    }

    if (result.size() != 25) {
      printf("Ignoring prefix \"%s\" (Invalid size)\n", prefix.c_str());
      return false;
    }

    //printf("VanitySearch: Found prefix %s\n",GetHex(result).c_str() );
    it->sPrefix = *(prefix_t *)(result.data() + 1);

    dummy1.append("1");
    DecodeBase58(dummy1, result);

    if (result.size() == 25) {
      //printf("VanitySearch: Found prefix %s\n", GetHex(result).c_str());
      it->sPrefix = *(prefix_t *)(result.data() + 1);
      nbDigit++;
    }

    // Difficulty
    it->difficulty = pow(2, 192) / pow(58, nbDigit);
    it->isFull = false;
    it->lPrefix = 0;
    it->prefix = (char *)prefix.c_str();
    it->prefixLength = (int)prefix.length();
    it->found = false;

    return true;

  }
}

// ----------------------------------------------------------------------------

void VanitySearch::dumpPrefixes() {

  for (int i = 0; i < 0xFFFF; i++) {
    if (prefixes[i].items) {
      printf("%04X\n", i);
      std::vector<PREFIX_ITEM> *items = prefixes[i].items;
      for (int j = 0; j < (*items).size(); j++) {
        printf("  %d\n", (*items)[j].sPrefix);
        printf("  %g\n", (*items)[j].difficulty);
        printf("  %s\n", (*items)[j].prefix);
      }
    }
  }

}

// ----------------------------------------------------------------------------

double VanitySearch::getDiffuclty() {

  double min = pow(2,160);

  if (onlyFull)
    return min;

  for (int i = 0; i < (int)usedPrefix.size(); i++) {
    int p = usedPrefix[i];
    std::vector<PREFIX_ITEM>& items = *prefixes[p].items;
    for (int j = 0; j < items.size(); j++) {
      if (!items[j].found) {
        if(items[j].difficulty<min)
          min = items[j].difficulty;
      }
    }
  }

  return min;

}

double log1(double x) {
  // Use taylor series to approximate log(1-x)
  return -x - (x*x)/2.0 - (x*x*x)/3.0 - (x*x*x*x)/4.0;
}

string VanitySearch::GetExpectedTime(double keyRate,double keyCount) {

  char tmp[128];
  string ret;

  double P = 1.0/ _difficulty;
  // pow(1-P,keyCount) is the probality of failure after keyCount tries
  double cP = 1.0 - pow(1-P,keyCount);

  sprintf(tmp,"[P %.2f%%]",cP*100.0);
  ret = string(tmp);
  
  double desiredP = 0.5;
  while(desiredP<cP)
    desiredP += 0.1;
  if(desiredP>=0.99) desiredP = 0.99;
  double k = log(1.0-desiredP)/log(1.0-P);
  if (isinf(k)) {
    // Try taylor
    k = log(1.0 - desiredP)/log1(P);
  }
  double dTime = (k-keyCount)/keyRate; // Time to perform k tries

  if(dTime<0) dTime = 0;

  double nbDay  = dTime / 86400.0;
  if (nbDay >= 1) {

    double nbYear = nbDay/365.0;
    if (nbYear > 1) {
      if(nbYear<5)
        sprintf(tmp, "[%.2f%% in %.1fy]", desiredP*100.0, nbYear);
      else
        sprintf(tmp, "[%.2f%% in %gy]", desiredP*100.0, nbYear);
    } else {
      sprintf(tmp, "[%.2f%% in %.1fd]", desiredP*100.0, nbDay);
    }

  } else {

    int iTime = (int)dTime;
    int nbHour = (int)((iTime % 86400) / 3600);
    int nbMin = (int)(((iTime % 86400) % 3600) / 60);
    int nbSec = (int)(iTime % 60);

    sprintf(tmp, "[%.2f%% in %02d:%02d:%02d]", desiredP*100.0, nbHour, nbMin, nbSec);

  }

  return ret + string(tmp);

}

// ----------------------------------------------------------------------------

void VanitySearch::output(string addr,string pAddr,string pAddrHex) {

#ifdef WIN64
   WaitForSingleObject(ghMutex,INFINITE);
#else
  pthread_mutex_lock(&ghMutex);
#endif
  
  FILE *f = stdout;
  bool needToClose = false;

  if (outputFile.length() > 0) {
    f = fopen(outputFile.c_str(), "a");
    if (f == NULL) {
      printf("Cannot open %s for writing\n", outputFile.c_str());
      f = stdout;
    } else {
      needToClose = true;
    }
  }

  fprintf(f, "\nPub Addr: %s\n", addr.c_str());

  if (startPubKeySpecified) {

    fprintf(f, "PartialPriv: %s\n", pAddr.c_str());

  } else {

    switch (searchType) {
    case P2PKH:
      fprintf(f, "Priv (WIF): p2pkh:%s\n", pAddr.c_str());
      break;
    case P2SH:
      fprintf(f, "Priv (WIF): p2wpkh-p2sh:%s\n", pAddr.c_str());
      break;
    case BECH32:
      fprintf(f, "Priv (WIF): p2wpkh:%s\n", pAddr.c_str());
      break;
    }
    fprintf(f, "Priv (HEX): 0x%s\n", pAddrHex.c_str());

  }

  if(needToClose)
    fclose(f);

#ifdef WIN64
  ReleaseMutex(ghMutex);
#else
  pthread_mutex_unlock(&ghMutex);
#endif

}

// ----------------------------------------------------------------------------

void VanitySearch::updateFound() {

  // Check if all prefixes has been found
  // Needed only if stopWhenFound is asked
  if (stopWhenFound) {

    bool allFound = true;
    for (int i = 0; i < usedPrefix.size(); i++) {
      bool iFound = true;
      if (!prefixes[usedPrefix[i]].found) {
        std::vector<PREFIX_ITEM>& items = *prefixes[usedPrefix[i]].items;
        for (int j = 0; j < items.size(); j++)
          iFound &= items[j].found;
        prefixes[usedPrefix[i]].found = iFound;
      }
      allFound &= iFound;
    }
    endOfSearch = allFound;

    // Update difficulty to the next most probable item
    _difficulty = getDiffuclty();

  }

}

// ----------------------------------------------------------------------------

bool VanitySearch::checkPrivKey(string addr, Int &key, int32_t incr, int endomorphism, bool mode) {

  Int k(&key);
  Point sp = startPubKey;

  if (incr < 0) {
    k.Add((uint64_t)(-incr));
    k.Neg();
    k.Add(&secp->order);
    if (startPubKeySpecified) sp.y.ModNeg();
  } else {
    k.Add((uint64_t)incr);
  }

  // Endomorphisms
  switch (endomorphism) {
  case 1:
    k.ModMulK1order(&lambda);
    if(startPubKeySpecified) sp.x.ModMulK1(&beta);
    break;
  case 2:
    k.ModMulK1order(&lambda2);
    if (startPubKeySpecified) sp.x.ModMulK1(&beta2);
    break;
  }

  // Check addresses
  Point p = secp->ComputePublicKey(&k);
  if (startPubKeySpecified) p = secp->AddDirect(p, sp);

  string chkAddr = secp->GetAddress(searchType, mode, p);
  if (chkAddr != addr) {

    //Key may be the opposite one (negative zero or compressed key)
    k.Neg();
    k.Add(&secp->order);
    p = secp->ComputePublicKey(&k);
    if (startPubKeySpecified) {
      sp.y.ModNeg();
      p = secp->AddDirect(p, sp);
    }
    string chkAddr = secp->GetAddress(searchType, mode, p);
    if (chkAddr != addr) {
      printf("\nWarning, wrong private key generated !\n");
      printf("  Addr :%s\n", addr.c_str());
      printf("  Check:%s\n", chkAddr.c_str());
      printf("  Endo:%d incr:%d comp:%d\n", endomorphism, incr, mode);
      return false;
    }

  }

  output(addr, secp->GetPrivAddress(mode ,k), k.GetBase16());

  return true;

}

void VanitySearch::checkAddr(int prefIdx, uint8_t *hash160, Int &key, int32_t incr, int endomorphism, bool mode) {

  vector<PREFIX_ITEM>& items = *prefixes[prefIdx].items;
  
  if (onlyFull) {
 
// Full addresses
    for (int i = 0; i < items.size(); i++) {

      if(stopWhenFound && items[i].found)
        continue;

      if (ripemd160_comp_hash(items[i].hash160, hash160) ) {

        // Found it !
        // You believe it ?
        if (checkPrivKey(secp->GetAddress(searchType,mode,hash160), key, incr, endomorphism, mode)) {
          // Mark it as found
          items[i].found = true;
          nbFoundKey++;
          updateFound();
        }
        
      }

    }
    
  } else {
 
    char a[64];
 
    string addr = secp->GetAddress(searchType, mode, hash160);

    for (int i = 0; i < items.size(); i++) {

      if(stopWhenFound && items[i].found)
        continue;
        
      strncpy(a, addr.c_str(),items[i].prefixLength);
      a[items[i].prefixLength] = 0;
        
      if (strcmp(items[i].prefix, a) == 0) {

        // Found it !
        if (checkPrivKey(addr, key, incr, endomorphism, mode)) {
          // Mark it as found
          items[i].found = true;
          nbFoundKey++;
          updateFound();
        }

      }

    }

  }
  
}

// ----------------------------------------------------------------------------

#ifdef WIN64
DWORD WINAPI _FindKey(LPVOID lpParam) {
#else
void *_FindKey(void *lpParam) {
#endif
  TH_PARAM *p = (TH_PARAM *)lpParam;
  p->obj->FindKeyCPU(p);
  return 0;
}

#ifdef WIN64
DWORD WINAPI _FindKeyGPU(LPVOID lpParam) {
#else
void *_FindKeyGPU(void *lpParam) {
#endif
  TH_PARAM *p = (TH_PARAM *)lpParam;
  p->obj->FindKeyGPU(p);
  return 0;
}

// ----------------------------------------------------------------------------

void VanitySearch::checkAddresses(bool compressed, Int key, int i, Point p1) {

  unsigned char h0[20];
  Point pte1[1];
  Point pte2[1];

  // Point
  secp->GetHash160(searchType,compressed, p1, h0);
  prefix_t pr0 = *(prefix_t *)h0;
  if (prefixes[pr0].items)
    checkAddr(pr0, h0, key, i, 0, compressed);

  // Endomorphism #1
  pte1[0].x.ModMulK1(&p1.x, &beta);
  pte1[0].y.Set(&p1.y);

  secp->GetHash160(searchType, compressed, pte1[0], h0);

  pr0 = *(prefix_t *)h0;
  if (prefixes[pr0].items)
    checkAddr(pr0, h0, key, i, 1, compressed);

  // Endomorphism #2
  pte2[0].x.ModMulK1(&p1.x, &beta2);
  pte2[0].y.Set(&p1.y);

  secp->GetHash160(searchType, compressed, pte2[0], h0);

  pr0 = *(prefix_t *)h0;
  if (prefixes[pr0].items)
    checkAddr(pr0, h0, key, i, 2, compressed);

  // Curve symetrie
  // if (x,y) = k*G, then (x, -y) is -k*G
  p1.y.ModNeg();
  secp->GetHash160(searchType, compressed, p1, h0);
  pr0 = *(prefix_t *)h0;
  if (prefixes[pr0].items)
    checkAddr(pr0, h0, key, -i, 0, compressed);

  // Endomorphism #1
  pte1[0].y.ModNeg();

  secp->GetHash160(searchType, compressed, pte1[0], h0);

  pr0 = *(prefix_t *)h0;
  if (prefixes[pr0].items)
    checkAddr(pr0, h0, key, -i, 1, compressed);

  // Endomorphism #2
  pte2[0].y.ModNeg();

  secp->GetHash160(searchType, compressed, pte2[0], h0);

  pr0 = *(prefix_t *)h0;
  if (prefixes[pr0].items)
    checkAddr(pr0, h0, key, -i, 2, compressed);

}

// ----------------------------------------------------------------------------

void VanitySearch::checkAddressesSSE(bool compressed,Int key, int i, Point p1, Point p2, Point p3, Point p4) {

  unsigned char h0[20];
  unsigned char h1[20];
  unsigned char h2[20];
  unsigned char h3[20];
  Point pte1[4];
  Point pte2[4];

  // Point -------------------------------------------------------------------------
  secp->GetHash160(searchType, compressed, p1, p2, p3, p4, h0, h1, h2, h3);

  prefix_t pr0 = *(prefix_t *)h0;
  prefix_t pr1 = *(prefix_t *)h1;
  prefix_t pr2 = *(prefix_t *)h2;
  prefix_t pr3 = *(prefix_t *)h3;

  if (prefixes[pr0].items)
    checkAddr(pr0, h0, key, i, 0, compressed);
  if (prefixes[pr1].items)
    checkAddr(pr1, h1, key, i + 1, 0, compressed);
  if (prefixes[pr2].items)
    checkAddr(pr2, h2, key, i + 2, 0, compressed);
  if (prefixes[pr3].items)
    checkAddr(pr3, h3, key, i + 3, 0, compressed);

  // Endomorphism #1
  // if (x, y) = k * G, then (beta*x, y) = lambda*k*G
  pte1[0].x.ModMulK1(&p1.x, &beta);
  pte1[0].y.Set(&p1.y);
  pte1[1].x.ModMulK1(&p2.x, &beta);
  pte1[1].y.Set(&p2.y);
  pte1[2].x.ModMulK1(&p3.x, &beta);
  pte1[2].y.Set(&p3.y);
  pte1[3].x.ModMulK1(&p4.x, &beta);
  pte1[3].y.Set(&p4.y);

  secp->GetHash160(searchType, compressed, pte1[0], pte1[1], pte1[2], pte1[3], h0, h1, h2, h3);

  pr0 = *(prefix_t *)h0;
  pr1 = *(prefix_t *)h1;
  pr2 = *(prefix_t *)h2;
  pr3 = *(prefix_t *)h3;

  if (prefixes[pr0].items)
    checkAddr(pr0, h0, key, i, 1, compressed);
  if (prefixes[pr1].items)
    checkAddr(pr1, h1, key, (i + 1), 1, compressed);
  if (prefixes[pr2].items)
    checkAddr(pr2, h2, key, (i + 2), 1, compressed);
  if (prefixes[pr3].items)
    checkAddr(pr3, h3, key, (i + 3), 1, compressed);

  // Endomorphism #2
  // if (x, y) = k * G, then (beta2*x, y) = lambda2*k*G
  pte2[0].x.ModMulK1(&p1.x, &beta2);
  pte2[0].y.Set(&p1.y);
  pte2[1].x.ModMulK1(&p2.x, &beta2);
  pte2[1].y.Set(&p2.y);
  pte2[2].x.ModMulK1(&p3.x, &beta2);
  pte2[2].y.Set(&p3.y);
  pte2[3].x.ModMulK1(&p4.x, &beta2);
  pte2[3].y.Set(&p4.y);

  secp->GetHash160(searchType, compressed, pte2[0], pte2[1], pte2[2], pte2[3], h0, h1, h2, h3);

  pr0 = *(prefix_t *)h0;
  pr1 = *(prefix_t *)h1;
  pr2 = *(prefix_t *)h2;
  pr3 = *(prefix_t *)h3;

  if (prefixes[pr0].items)
    checkAddr(pr0, h0, key, i, 2, compressed);
  if (prefixes[pr1].items)
    checkAddr(pr1, h1, key, (i + 1), 2, compressed);
  if (prefixes[pr2].items)
    checkAddr(pr2, h2, key, (i + 2), 2, compressed);
  if (prefixes[pr3].items)
    checkAddr(pr3, h3, key, (i + 3), 2, compressed);

  // Curve symetrie -------------------------------------------------------------------------
  // if (x,y) = k*G, then (x, -y) is -k*G

  p1.y.ModNeg();
  p2.y.ModNeg();
  p3.y.ModNeg();
  p4.y.ModNeg();

  secp->GetHash160(searchType, compressed, p1, p2, p3, p4, h0, h1, h2, h3);

  pr0 = *(prefix_t *)h0;
  pr1 = *(prefix_t *)h1;
  pr2 = *(prefix_t *)h2;
  pr3 = *(prefix_t *)h3;

  if (prefixes[pr0].items)
    checkAddr(pr0, h0, key, -i, 0, compressed);
  if (prefixes[pr1].items)
    checkAddr(pr1, h1, key, -(i + 1), 0, compressed);
  if (prefixes[pr2].items)
    checkAddr(pr2, h2, key, -(i + 2), 0, compressed);
  if (prefixes[pr3].items)
    checkAddr(pr3, h3, key, -(i + 3), 0, compressed);

  // Endomorphism #1
  // if (x, y) = k * G, then (beta*x, y) = lambda*k*G
  pte1[0].y.ModNeg();
  pte1[1].y.ModNeg();
  pte1[2].y.ModNeg();
  pte1[3].y.ModNeg();


  secp->GetHash160(searchType, compressed, pte1[0], pte1[1], pte1[2], pte1[3], h0, h1, h2, h3);

  pr0 = *(prefix_t *)h0;
  pr1 = *(prefix_t *)h1;
  pr2 = *(prefix_t *)h2;
  pr3 = *(prefix_t *)h3;

  if (prefixes[pr0].items)
    checkAddr(pr0, h0, key, -i, 1, compressed);
  if (prefixes[pr1].items)
    checkAddr(pr1, h1, key, -(i + 1), 1, compressed);
  if (prefixes[pr2].items)
    checkAddr(pr2, h2, key, -(i + 2), 1, compressed);
  if (prefixes[pr3].items)
    checkAddr(pr3, h3, key, -(i + 3), 1, compressed);

  // Endomorphism #2
  // if (x, y) = k * G, then (beta2*x, y) = lambda2*k*G
  pte2[0].y.ModNeg();
  pte2[1].y.ModNeg();
  pte2[2].y.ModNeg();
  pte2[3].y.ModNeg();

  secp->GetHash160(searchType, compressed, pte2[0], pte2[1], pte2[2], pte2[3], h0, h1, h2, h3);

  pr0 = *(prefix_t *)h0;
  pr1 = *(prefix_t *)h1;
  pr2 = *(prefix_t *)h2;
  pr3 = *(prefix_t *)h3;

  if (prefixes[pr0].items)
    checkAddr(pr0, h0, key, -i, 2, compressed);
  if (prefixes[pr1].items)
    checkAddr(pr1, h1, key, -(i + 1), 2, compressed);
  if (prefixes[pr2].items)
    checkAddr(pr2, h2, key, -(i + 2), 2, compressed);
  if (prefixes[pr3].items)
    checkAddr(pr3, h3, key, -(i + 3), 2, compressed);

}

// ----------------------------------------------------------------------------
void VanitySearch::getCPUStartingKey(int thId,Int& key,Point& startP) {

  if (rekey > 0) {
    key.Rand(256);
  } else {
    key.Set(&startKey);
    Int off((int64_t)thId);
    off.ShiftL(64);
    key.Add(&off);
  }
  Int km(&key);
  
  km.Add((uint64_t)CPU_GRP_SIZE / 2);
  startP = secp->ComputePublicKey(&km);
  
  if(startPubKeySpecified)
   startP = secp->AddDirect(startP,startPubKey);

}

void VanitySearch::FindKeyCPU(TH_PARAM *ph) {

  // Global init
  int thId = ph->threadId;
  counters[thId] = 0;

  // CPU Thread
  IntGroup *grp = new IntGroup(CPU_GRP_SIZE/2+1);

  // Group Init
  Int  key;
  Point startP;
  getCPUStartingKey(thId,key,startP);

  Int dx[CPU_GRP_SIZE/2+1];
  Point pts[CPU_GRP_SIZE];

  Int dy;
  Int dyn;
  Int _s;
  Int _p;
  Point pp;
  Point pn;
  grp->Set(dx);

  ph->hasStarted = true;
  ph->rekeyRequest = false;

  while (!endOfSearch) {

    if (ph->rekeyRequest) {
      getCPUStartingKey(thId, key, startP);
      ph->rekeyRequest = false;
    }

    // Fill group
    int i;
    int hLength = (CPU_GRP_SIZE / 2 - 1);

    for (i = 0; i < hLength; i++) {
      dx[i].ModSub(&Gn[i].x, &startP.x);
    }
    dx[i].ModSub(&Gn[i].x, &startP.x);  // For the first point
    dx[i+1].ModSub(&_2Gn.x, &startP.x); // For the next center point

    // Grouped ModInv
    grp->ModInv();

    // We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse
    // We compute key in the positive and negative way from the center of the group

    // center point
    pts[CPU_GRP_SIZE/2] = startP;

    for (i = 0; i<hLength && !endOfSearch; i++) {

      pp = startP;
      pn = startP;

      // P = startP + i*G
      dy.ModSub(&Gn[i].y,&pp.y);

      _s.ModMulK1(&dy, &dx[i]);       // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
      _p.ModSquareK1(&_s);            // _p = pow2(s)

      pp.x.ModNeg();
      pp.x.ModAdd(&_p);
      pp.x.ModSub(&Gn[i].x);           // rx = pow2(s) - p1.x - p2.x;

      pp.y.ModSub(&Gn[i].x, &pp.x);
      pp.y.ModMulK1(&_s);
      pp.y.ModSub(&Gn[i].y);           // ry = - p2.y - s*(ret.x-p2.x);  

      // P = startP - i*G  , if (x,y) = i*G then (x,-y) = -i*G
      dyn.Set(&Gn[i].y);
      dyn.ModNeg();
      dyn.ModSub(&pn.y);

      _s.ModMulK1(&dyn, &dx[i]);      // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
      _p.ModSquareK1(&_s);            // _p = pow2(s)

      pn.x.ModNeg();
      pn.x.ModAdd(&_p);
      pn.x.ModSub(&Gn[i].x);          // rx = pow2(s) - p1.x - p2.x;

      pn.y.ModSub(&Gn[i].x, &pn.x);
      pn.y.ModMulK1(&_s);
      pn.y.ModAdd(&Gn[i].y);          // ry = - p2.y - s*(ret.x-p2.x);  

      pts[CPU_GRP_SIZE/2 + (i+1)] = pp;
      pts[CPU_GRP_SIZE/2 - (i+1)] = pn;

    }

    // First point (startP - (GRP_SZIE/2)*G)
    pn = startP;
    dyn.Set(&Gn[i].y);
    dyn.ModNeg();
    dyn.ModSub(&pn.y);

    _s.ModMulK1(&dyn, &dx[i]);
    _p.ModSquareK1(&_s);

    pn.x.ModNeg();
    pn.x.ModAdd(&_p);
    pn.x.ModSub(&Gn[i].x);

    pn.y.ModSub(&Gn[i].x, &pn.x);
    pn.y.ModMulK1(&_s);
    pn.y.ModAdd(&Gn[i].y);

    pts[0] = pn;

    // Next start point (startP + GRP_SIZE*G)
    pp = startP;
    dy.ModSub(&_2Gn.y, &pp.y);

    _s.ModMulK1(&dy, &dx[i+1]);
    _p.ModSquareK1(&_s);

    pp.x.ModNeg();
    pp.x.ModAdd(&_p);
    pp.x.ModSub(&_2Gn.x);

    pp.y.ModSub(&_2Gn.x, &pp.x);
    pp.y.ModMulK1(&_s);
    pp.y.ModSub(&_2Gn.y);
    startP = pp;

#if 0
    // Check
    {
      bool wrong = false;
      Point p0 = secp.ComputePublicKey(&key);
      for (int i = 0; i < CPU_GRP_SIZE; i++) {
        if (!p0.equals(pts[i])) {
          wrong = true;
          printf("[%d] wrong point\n",i);
        }
        p0 = secp.NextKey(p0);
      }
      if(wrong) exit(0);
    }
#endif

    // Check addresses
    if (useSSE) {

      for (int i = 0; i < CPU_GRP_SIZE && !endOfSearch; i += 4) {

        switch (searchMode) {
          case SEARCH_COMPRESSED:
            checkAddressesSSE(true, key, i, pts[i], pts[i + 1], pts[i + 2], pts[i + 3]);
            break;
          case SEARCH_UNCOMPRESSED:
            checkAddressesSSE(false, key, i, pts[i], pts[i + 1], pts[i + 2], pts[i + 3]);
            break;
          case SEARCH_BOTH:
            checkAddressesSSE(true, key, i, pts[i], pts[i + 1], pts[i + 2], pts[i + 3]);
            checkAddressesSSE(false, key, i, pts[i], pts[i + 1], pts[i + 2], pts[i + 3]);
            break;
        }

      }

    } else {

      for (int i = 0; i < CPU_GRP_SIZE && !endOfSearch; i ++) {

        switch (searchMode) {
        case SEARCH_COMPRESSED:
          checkAddresses(true, key, i, pts[i]);
          break;
        case SEARCH_UNCOMPRESSED:
          checkAddresses(false, key, i, pts[i]);
          break;
        case SEARCH_BOTH:
          checkAddresses(true, key, i, pts[i]);
          checkAddresses(false, key, i, pts[i]);
          break;
        }

      }

    }

    key.Add((uint64_t)CPU_GRP_SIZE);
    counters[thId]+= 6*CPU_GRP_SIZE; // Point + endo #1 + endo #2 + Symetric point + endo #1 + endo #2

  }

  ph->isRunning = false;

}

// ----------------------------------------------------------------------------

void VanitySearch::getGPUStartingKeys(int thId, int groupSize, int nbThread, Int *keys, Point *p) {

  for (int i = 0; i < nbThread; i++) {
    if (rekey > 0) {
      keys[i].Rand(64);
    } else {
      keys[i].Set(&startKey);
      Int offT((uint64_t)i);
      offT.ShiftL(80);
      Int offG((uint64_t)thId);
      offG.ShiftL(112);
      keys[i].Add(&offT);
      keys[i].Add(&offG);
    }
    Int k(keys + i);
    // Starting key is at the middle of the group
    k.Add((uint64_t)(groupSize / 2));
    p[i] = secp->ComputePublicKey(&k);
    if (startPubKeySpecified)
      p[i] = secp->AddDirect(p[i], startPubKey);
  }

}

void VanitySearch::FindKeyGPU(TH_PARAM *ph) {

  bool ok = true;

#ifdef WITHGPU

  // Global init
  int thId = ph->threadId;
  GPUEngine g(ph->gridSize, ph->gpuId, maxFound, (rekey!=0));
  int nbThread = g.GetNbThread();
  Point *p = new Point[nbThread];
  Int *keys = new Int[nbThread];
  vector<ITEM> found;

  printf("GPU: %s\n",g.deviceName.c_str());

  counters[thId] = 0;

  getGPUStartingKeys(thId, g.GetGroupSize(), nbThread, keys, p);

  g.SetSearchMode(searchMode);
  g.SetSearchType(searchType);
  if (onlyFull) {
    g.SetPrefix(usedPrefixL,nbPrefix);
  } else {
    g.SetPrefix(usedPrefix);
  }

  getGPUStartingKeys(thId, g.GetGroupSize(), nbThread, keys, p);
  ok = g.SetKeys(p);
  ph->rekeyRequest = false;

  ph->hasStarted = true;

  // GPU Thread
  while (ok && !endOfSearch) {

    if (ph->rekeyRequest) {
      getGPUStartingKeys(thId, g.GetGroupSize(), nbThread, keys, p);
      ok = g.SetKeys(p);
      ph->rekeyRequest = false;
    }

    // Call kernel
    ok = g.Launch(found);

    for(int i=0;i<(int)found.size() && !endOfSearch;i++) {

      ITEM it = found[i];
      checkAddr(*(prefix_t *)(it.hash), it.hash, keys[it.thId], it.incr, it.endo, it.mode);
 
    }

    if (ok) {
      for (int i = 0; i < nbThread; i++) {
        keys[i].Add((uint64_t)STEP_SIZE);
      }
      counters[thId] += 6 * STEP_SIZE * nbThread; // Point +  endo1 + endo2 + symetrics
    }

  }

  delete[] keys;
  delete[] p;

#else
  ph->hasStarted = true;
  printf("GPU code not compiled, use -DWITHGPU when compiling.\n");
#endif

  ph->isRunning = false;

}

// ----------------------------------------------------------------------------

bool VanitySearch::isAlive(TH_PARAM *p) {

  bool isAlive = true;
  int total = nbCPUThread + nbGPUThread;
  for(int i=0;i<total;i++)
    isAlive = isAlive && p[i].isRunning;

  return isAlive;

}

// ----------------------------------------------------------------------------

bool VanitySearch::hasStarted(TH_PARAM *p) {

  bool hasStarted = true;
  int total = nbCPUThread + nbGPUThread;
  for (int i = 0; i < total; i++)
    hasStarted = hasStarted && p[i].hasStarted;

  return hasStarted;

}

// ----------------------------------------------------------------------------

void VanitySearch::rekeyRequest(TH_PARAM *p) {

  bool hasStarted = true;
  int total = nbCPUThread + nbGPUThread;
  for (int i = 0; i < total; i++)
  p[i].rekeyRequest = true;

}

// ----------------------------------------------------------------------------

uint64_t VanitySearch::getGPUCount() {

  uint64_t count = 0;
  for(int i=0;i<nbGPUThread;i++)
    count += counters[0x80L+i];
  return count;

}

uint64_t VanitySearch::getCPUCount() {

  uint64_t count = 0;
  for(int i=0;i<nbCPUThread;i++)
    count += counters[i];
  return count;

}

// ----------------------------------------------------------------------------

void VanitySearch::Search(int nbThread,std::vector<int> gpuId,std::vector<int> gridSize) {

  double t0;
  double t1;
  endOfSearch = false;
  nbCPUThread = nbThread;
  nbGPUThread = (useGpu?(int)gpuId.size():0);
  nbFoundKey = 0;

  memset(counters,0,sizeof(counters));

  printf("Number of CPU thread: %d\n", nbCPUThread);

  TH_PARAM *params = (TH_PARAM *)malloc((nbCPUThread + nbGPUThread) * sizeof(TH_PARAM));
  memset(params,0,(nbCPUThread + nbGPUThread) * sizeof(TH_PARAM));

  // Launch CPU threads
  for (int i = 0; i < nbCPUThread; i++) {
    params[i].obj = this;
    params[i].threadId = i;
    params[i].isRunning = true;

#ifdef WIN64
    DWORD thread_id;
    CreateThread(NULL, 0, _FindKey, (void*)(params+i), 0, &thread_id);
    ghMutex = CreateMutex(NULL, FALSE, NULL);
#else
    pthread_t thread_id;
    pthread_create(&thread_id, NULL, &_FindKey, (void*)(params+i));  
    ghMutex = PTHREAD_MUTEX_INITIALIZER;
#endif
  }

  // Launch GPU threads
  for (int i = 0; i < nbGPUThread; i++) {
    params[nbCPUThread+i].obj = this;
    params[nbCPUThread+i].threadId = 0x80L+i;
    params[nbCPUThread+i].isRunning = true;
    params[nbCPUThread+i].gpuId = gpuId[i];
    params[nbCPUThread+i].gridSize = gridSize[i];
#ifdef WIN64
    DWORD thread_id;
    CreateThread(NULL, 0, _FindKeyGPU, (void*)(params+(nbCPUThread+i)), 0, &thread_id);
#else
    pthread_t thread_id;
    pthread_create(&thread_id, NULL, &_FindKeyGPU, (void*)(params+(nbCPUThread+i)));  
#endif
  }

#ifndef WIN64
  setvbuf(stdout, NULL, _IONBF, 0);
#endif

  uint64_t lastCount = 0;
  uint64_t gpuCount = 0;
  uint64_t lastGPUCount = 0;

  // Key rate smoothing filter
  #define FILTER_SIZE 8
  double lastkeyRate[FILTER_SIZE];
  double lastGpukeyRate[FILTER_SIZE];
  uint32_t filterPos = 0;

  double keyRate = 0.0;
  double gpuKeyRate = 0.0;

  memset(lastkeyRate,0,sizeof(lastkeyRate));
  memset(lastGpukeyRate,0,sizeof(lastkeyRate));

  // Wait that all threads have started
  while (!hasStarted(params)) {
    Timer::SleepMillis(500);
  }

  t0 = Timer::get_tick();
  startTime = t0;

  while (isAlive(params)) {

    int delay = 2000;
    while (isAlive(params) && delay>0) {
      Timer::SleepMillis(500);
      delay -= 500;
    }

    gpuCount = getGPUCount();
    uint64_t count = getCPUCount() + gpuCount;

    t1 = Timer::get_tick();
    keyRate = (double)(count - lastCount) / (t1 - t0);
    gpuKeyRate = (double)(gpuCount - lastGPUCount) / (t1 - t0);
    lastkeyRate[filterPos%FILTER_SIZE] = keyRate;
    lastGpukeyRate[filterPos%FILTER_SIZE] = gpuKeyRate;
    filterPos++;

    // KeyRate smoothing
    double avgKeyRate = 0.0;
    double avgGpuKeyRate = 0.0;
    uint32_t nbSample;
    for (nbSample = 0; (nbSample < FILTER_SIZE) && (nbSample < filterPos); nbSample++) {
      avgKeyRate += lastkeyRate[nbSample];
      avgGpuKeyRate += lastGpukeyRate[nbSample];
    }
    avgKeyRate /= (double)(nbSample);
    avgGpuKeyRate /= (double)(nbSample);

    if (isAlive(params)) {
      printf("%.3f MK/s (GPU %.3f MK/s) (2^%.2f) %s[%d]  \r",
        avgKeyRate / 1000000.0, avgGpuKeyRate / 1000000.0,
          log2((double)count), GetExpectedTime(avgKeyRate, (double)count).c_str(),nbFoundKey);
    }

    if (rekey > 0) {
      if ((count - lastRekey) > (1000000 * rekey)) {
        // Rekey request
        rekeyRequest(params);
        lastRekey = count;
      }
    }

    lastCount = count;
    lastGPUCount = gpuCount;
    t0 = t1;

  }

  free(params);

}

// ----------------------------------------------------------------------------

string VanitySearch::GetHex(vector<unsigned char> &buffer) {

  string ret;

  char tmp[128];
  for (int i = 0; i < (int)buffer.size(); i++) {
    sprintf(tmp,"%02X",buffer[i]);
    ret.append(tmp);
  }

  return ret;

}


c++ coders please help me how to modify this to work on 64 bit rand not 256 bit rand. c++ really hard to me to understand
WanderingPhilospher
Full Member
***
Offline Offline

Activity: 1064
Merit: 219

Shooters Shoot...


View Profile
March 14, 2021, 07:57:30 PM
 #934

hi i want to generate 64 bit not full 256 now i change "keys.Rand(256);" to "keys.Rand(64);" on VanitySearch::getGPUStartingKeys but only some keys are  64 bit what i am missing i am new on c++
most of keys found will be outside of 64 bit due to the endo and symm. Basically the program takes in inputted key, say 64 bit, but then checks it and 5 other keys related to that 64 bit key. So you would have to comment out those sections if you want all keys in the 64 bit range.
can you help me which code section need i comment

c++ coders please help me how to modify this to work on 64 bit rand not 256 bit rand. c++ really hard to me to understand
You will also have to modify the Main.cpp (at the minimum)
NotATether
Legendary
*
Offline Offline

Activity: 1596
Merit: 6730


bitcoincleanup.com / bitmixlist.org


View Profile WWW
March 15, 2021, 08:46:47 AM
 #935

Quote
c++ coders please help me how to modify this to work on 64 bit rand not 256 bit rand. c++ really hard to me to understand

In Kangaroo.cpp try changing this line:

Code:
void VanitySearch::getCPUStartingKey(int thId,Int& key,Point& startP) {

  if (rekey > 0) {
    key.Rand(256); <--- this line
...

To key.Rand(64). This is going to change the starting key to be a 64-bit random int, same for all subsequent keys.

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
Dr88
Newbie
*
Offline Offline

Activity: 15
Merit: 0


View Profile
March 15, 2021, 02:38:09 PM
 #936

Quote
c++ coders please help me how to modify this to work on 64 bit rand not 256 bit rand. c++ really hard to me to understand

In Kangaroo.cpp try changing this line:

Code:
void VanitySearch::getCPUStartingKey(int thId,Int& key,Point& startP) {

  if (rekey > 0) {
    key.Rand(256); <--- this line
...

To key.Rand(64). This is going to change the starting key to be a 64-bit random int, same for all subsequent keys.

thank you. but i already did that i am using gpu so changed keys.Rand(256);" to "keys.Rand(64);" on VanitySearch::getGPUStartingKeys but when i run VanitySearch.exe -t 0 -r 1 -gpu -o info.txt 1Lx  only some keys 64 bit .

dude above suggest me to comment code blocks related endo and sym i tryed but got compile error then some tests again got key error .
WanderingPhilospher
Full Member
***
Offline Offline

Activity: 1064
Merit: 219

Shooters Shoot...


View Profile
March 15, 2021, 03:26:31 PM
 #937

Quote
c++ coders please help me how to modify this to work on 64 bit rand not 256 bit rand. c++ really hard to me to understand

To key.Rand(64). This is going to change the starting key to be a 64-bit random int, same for all subsequent keys.

thank you. but i already did that i am using gpu so changed keys.Rand(256);" to "keys.Rand(64);" on VanitySearch::getGPUStartingKeys but when i run VanitySearch.exe -t 0 -r 1 -gpu -o info.txt 1Lx  only some keys 64 bit .

dude above suggest me to comment code blocks related endo and sym i tryed but got compile error then some tests again got key error .
Are you just trying to randomly generate only 64 bit keys to look for #64 of challenge/puzzle?
Dr88
Newbie
*
Offline Offline

Activity: 15
Merit: 0


View Profile
March 15, 2021, 03:39:31 PM
 #938

Quote
c++ coders please help me how to modify this to work on 64 bit rand not 256 bit rand. c++ really hard to me to understand

To key.Rand(64). This is going to change the starting key to be a 64-bit random int, same for all subsequent keys.

thank you. but i already did that i am using gpu so changed keys.Rand(256);" to "keys.Rand(64);" on VanitySearch::getGPUStartingKeys but when i run VanitySearch.exe -t 0 -r 1 -gpu -o info.txt 1Lx  only some keys 64 bit .

dude above suggest me to comment code blocks related endo and sym i tryed but got compile error then some tests again got key error .
Are you just trying to randomly generate only 64 bit keys to look for #64 of challenge/puzzle?
yes
WanderingPhilospher
Full Member
***
Offline Offline

Activity: 1064
Merit: 219

Shooters Shoot...


View Profile
March 15, 2021, 04:03:23 PM
 #939

Quote
c++ coders please help me how to modify this to work on 64 bit rand not 256 bit rand. c++ really hard to me to understand
To key.Rand(64). This is going to change the starting key to be a 64-bit random int, same for all subsequent keys.
dude above suggest me to comment code blocks related endo and sym i tryed but got compile error then some tests again got key error .
Are you just trying to randomly generate only 64 bit keys to look for #64 of challenge/puzzle?
yes
Something like this:

Code:
VanBitKracken
RandomMode
Range Start=8000000000000000
  Range End=FFFFFFFFFFFFFFFF
Searching For: 16jY7qLJnxb7CHZyqBP8qca9d51gAjyXQN [Compressed]
Started Mon Mar 15 10:56:51 2021
CPU threads used: 0
GPU: GPU #4 GeForce RTX 2070 SUPER (40x64 cores) Grid(1024x512)
GPU: GPU #0 GeForce RTX 3070 (46x128 cores) Grid(1024x512)
GPU: GPU #5 GeForce RTX 2070 (36x64 cores) Grid(1024x512)
GPU: GPU #2 GeForce RTX 3070 (46x128 cores) Grid(1024x512)
GPU: GPU #1 GeForce RTX 3070 (46x128 cores) Grid(1024x512)
GPU: GPU #3 GeForce RTX 3070 (46x128 cores) Grid(1024x512)
Key 0: F8F7AB14B549D963
Key 1: E27A8E10F7B88360
Key 2: ABFE11261BBD4690
Key 3: F422548A1F4B2DAE
Key 0: FA88129A5AB50074
Key 1: B0341A673B1314D4
Key 2: C6719553AAD5A8C6
Key 3: D09C89B9E74DF9EE
Key 0: E9CC7B8BB752F5CB
Key 1: A7B789B6A94D60AD
Key 2: A741098EFA53130A
Key 3: 97FB2DB875755EA6
Key 0: F399AEDCE1F72EA8
Key 1: D24BDBDE76E19FAC
Key 2: 8F9A7FC4F8591C25
Key 3: CACFECB3F9230C7F
Key 0: F25D378E2916D696
Key 1: ED7EA9A718B61017
Key 2: FCDDD610A70AF071
Key 3: 893CF7F570EFB585
Key 0: D84FE1221CFDC77A
Key 1: D8445FE43B6D871E
Key 2: 8C323D909C23163C
Key 3: 867C5E6DA5D981D9
Key 524285: AA670B193E7CAA36
Key 524285: C6D15B55CC2DCA5A
Key 524286: C7901B0332FE38A9
Key 524286: EA11A526D7135C77
Key 524287: C5F35D538D961196
Key 524287: 8DA14E252E6DC1E7
Key 524285: D3FBF43E6888E2C0
Key 524286: F8F40F51C3388D6C
Key 524287: FB86E889D499BE6A
Key 524285: 8C639A3EEBBB486D
Key 524286: AFF06C39E04CF30D
Key 524287: D9A7EEE1CC93F155
Key 524285: CF060C3C274DB24A
Key 524286: C4349EEDE915A9A0
Key 524287: A57D8D77096307E4
Key 524285: B15B02DFB42CD315
Key 524286: A4F20EA9DABE20BB
[11419.89 Mkey/s][GPU 11419.89 Mkey/s][Private Keys Checked = 2^35.81] [00:00:07 Run Time ]  [Expected Run Time 34.7357y][Found 0]
jennamarble
Newbie
*
Offline Offline

Activity: 20
Merit: 0


View Profile
March 20, 2021, 07:05:39 AM
 #940

the -cp option at the moment does not convert private key hex to uncompressed address format i am sure this is not a bug also for convenience can you update -><

-cp option update:

add read from input file for -cp option where it can read bunch of private key in hex format from text file instead of single computation to leverage gpu horse power for converting pre computed private keys and converting to compressed and uncompressed address format there is no tool out there does this using gpu i am pretty most people want their pre computed private keys to be converted as a side benefit.

can somebody implement this please i have millions of private keys so it cannot be converted quickly to addresses with cpu because cpu is not powerful enough can somebody make small modification to the software where it read single hex private key to read those values from file this way we can convert millions of private keys using gpu thanks again for anyone out there who can help.
Pages: « 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 [47] 48 49 50 51 52 53 54 55 56 57 58 59 60 61 »
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!