Browse Source

Add keep pattern after match option, quiet option, and result file.

Bump version to 0.9
master
samr7 13 years ago
parent
commit
bcbaff3cf0
  1. 9
      CHANGELOG
  2. 182
      vanitygen.c

9
CHANGELOG

@ -32,3 +32,12 @@ Version 0.6, released July 8 2011:
Version 0.7, released July 8 2011: Version 0.7, released July 8 2011:
- Use GetLogicalProcessorInformation() to count CPUs on Windows, - Use GetLogicalProcessorInformation() to count CPUs on Windows,
because GetActiveProcessorCount() is Windows 7 and newer. because GetActiveProcessorCount() is Windows 7 and newer.
Version 0.8, released July 8 2011:
- Fix recalculation of difficulty after a match when searching
for multiple prefixes.
Version 0.9, released July 10 2011:
- Add flag to retain patterns after being matched
- Add output/result file option
- Add quiet option and clean up status bar display

182
vanitygen.c

@ -40,11 +40,13 @@
#include "winglue.c" #include "winglue.c"
#endif #endif
const char *version = "0.8"; const char *version = "0.9";
const int debug = 0; const int debug = 0;
int verbose = 0; int verbose = 1;
int remove_on_match = 1;
const char *result_file = NULL;
static const char *b58_alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; const char *b58_alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
void void
encode_b58_check(void *buf, size_t len, char *result) encode_b58_check(void *buf, size_t len, char *result)
@ -167,16 +169,18 @@ typedef struct _timing_info_s {
} timing_info_t; } timing_info_t;
void void
output_timing(int cycle, struct timeval *last, double chance) output_timing(int cycle, struct timeval *last,
unsigned long long found, unsigned long pattcount,
double chance)
{ {
static unsigned long long total; static unsigned long long total = 0, prevfound = 0, sincelast = 0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static timing_info_t *timing_head = NULL; static timing_info_t *timing_head = NULL;
pthread_t me; pthread_t me;
struct timeval tvnow, tv; struct timeval tvnow, tv;
timing_info_t *tip, *mytip; timing_info_t *tip, *mytip;
long long rate, myrate; unsigned long long rate, myrate;
double count, prob, time, targ; double count, prob, time, targ;
char linebuf[80]; char linebuf[80];
char *unit; char *unit;
@ -210,7 +214,12 @@ output_timing(int cycle, struct timeval *last, double chance)
} }
total += cycle; total += cycle;
count = total; if (prevfound != found) {
prevfound = found;
sincelast = 0;
}
sincelast += cycle;
count = sincelast;
if (mytip != timing_head) { if (mytip != timing_head) {
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
@ -228,12 +237,15 @@ output_timing(int cycle, struct timeval *last, double chance)
if (chance >= 1.0) { if (chance >= 1.0) {
prob = 1.0f - exp(-count/chance); prob = 1.0f - exp(-count/chance);
p = snprintf(&linebuf[p], rem, "[Prob %.1f%%]", prob * 100); if (prob <= 0.999) {
p = snprintf(&linebuf[p], rem, "[Prob %.1f%%]",
prob * 100);
assert(p > 0); assert(p > 0);
rem -= p; rem -= p;
if (rem < 0) if (rem < 0)
rem = 0; rem = 0;
p = sizeof(linebuf) - rem; p = sizeof(linebuf) - rem;
}
for (i = 0; i < sizeof(targs)/sizeof(targs[0]); i++) { for (i = 0; i < sizeof(targs)/sizeof(targs[0]); i++) {
targ = targs[i]; targ = targs[i];
@ -274,9 +286,22 @@ output_timing(int cycle, struct timeval *last, double chance)
rem -= p; rem -= p;
if (rem < 0) if (rem < 0)
rem = 0; rem = 0;
p = sizeof(linebuf) - rem;
} }
} }
if (found) {
if (pattcount)
p = snprintf(&linebuf[p], rem, "[Found %lld/%ld]",
found, pattcount);
else
p = snprintf(&linebuf[p], rem, "[Found %lld]", found);
assert(p > 0);
rem -= p;
if (rem < 0)
rem = 0;
}
if (rem) { if (rem) {
memset(&linebuf[sizeof(linebuf)-rem], 0x20, rem); memset(&linebuf[sizeof(linebuf)-rem], 0x20, rem);
linebuf[sizeof(linebuf)-1] = '\0'; linebuf[sizeof(linebuf)-1] = '\0';
@ -288,16 +313,21 @@ output_timing(int cycle, struct timeval *last, double chance)
void void
output_match(EC_KEY *pkey, const char *pattern, int addrtype, int privtype) output_match(EC_KEY *pkey, const char *pattern, int addrtype, int privtype)
{ {
char print_buf[512];
unsigned char key_buf[512], *pend; unsigned char key_buf[512], *pend;
char addr_buf[64];
char privkey_buf[128];
int len; int len;
assert(EC_KEY_check_key(pkey)); assert(EC_KEY_check_key(pkey));
encode_address(pkey, addrtype, addr_buf);
encode_privkey(pkey, privtype, privkey_buf);
printf("Pattern: %s\n", pattern); if (!result_file || (verbose > 0)) {
printf("\r%79s\rPattern: %s\n", "", pattern);
}
if (verbose) { if (verbose > 0) {
if (verbose > 1) {
/* Hexadecimal OpenSSL notation */ /* Hexadecimal OpenSSL notation */
pend = key_buf; pend = key_buf;
len = i2o_ECPublicKey(pkey, &pend); len = i2o_ECPublicKey(pkey, &pend);
@ -309,16 +339,31 @@ output_match(EC_KEY *pkey, const char *pattern, int addrtype, int privtype)
dumphex(key_buf, len); dumphex(key_buf, len);
} }
/* Base-58 bitcoin notation public key hash */ }
encode_address(pkey, addrtype, print_buf);
printf("Address: %s\n", print_buf);
/* Base-58 bitcoin notation private key */ if (!result_file || (verbose > 0)) {
encode_privkey(pkey, privtype, print_buf); printf("Address: %s\n"
printf("Privkey: %s\n", print_buf); "Privkey: %s\n",
addr_buf, privkey_buf);
}
if (result_file) {
FILE *fp = fopen(result_file, "a");
if (!fp) {
printf("ERROR: could not open result file: %s\n",
strerror(errno));
} else {
fprintf(fp,
"Pattern: %s\n"
"Address: %s\n"
"Privkey: %s\n",
pattern, addr_buf, privkey_buf);
fclose(fp);
}
}
} }
signed char b58_reverse_map[256] = { const signed char b58_reverse_map[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@ -1169,7 +1214,7 @@ typedef struct _prefix_case_iter_s {
int ci_value; int ci_value;
} prefix_case_iter_t; } prefix_case_iter_t;
unsigned char b58_case_map[256] = { const unsigned char b58_case_map[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -1227,9 +1272,11 @@ prefix_case_iter_next(prefix_case_iter_t *cip)
typedef struct _vg_prefix_context_s { typedef struct _vg_prefix_context_s {
avl_root_t vcp_avlroot; avl_root_t vcp_avlroot;
int vcp_npfx;
int vcp_addrtype; int vcp_addrtype;
int vcp_privtype; int vcp_privtype;
unsigned long vcp_npfx;
unsigned long vcp_npfx_start;
unsigned long long vcp_found;
double vcp_chance; double vcp_chance;
BIGNUM vcp_difficulty; BIGNUM vcp_difficulty;
pthread_mutex_t vcp_lock; pthread_mutex_t vcp_lock;
@ -1239,7 +1286,7 @@ void
vg_prefix_context_free(vg_prefix_context_t *vcpp) vg_prefix_context_free(vg_prefix_context_t *vcpp)
{ {
vg_prefix_t *vp; vg_prefix_t *vp;
int npfx_left = 0; unsigned long npfx_left = 0;
while (!avl_root_empty(&vcpp->vcp_avlroot)) { while (!avl_root_empty(&vcpp->vcp_avlroot)) {
vp = avl_item_entry(vcpp->vcp_avlroot.ar_root, vp = avl_item_entry(vcpp->vcp_avlroot.ar_root,
@ -1265,11 +1312,13 @@ vg_prefix_context_next_difficulty(vg_prefix_context_t *vcpp,
BN_div(bntmp2, NULL, bntmp, &vcpp->vcp_difficulty, bnctx); BN_div(bntmp2, NULL, bntmp, &vcpp->vcp_difficulty, bnctx);
dbuf = BN_bn2dec(bntmp2); dbuf = BN_bn2dec(bntmp2);
if (verbose > 0) {
if (vcpp->vcp_npfx > 1) if (vcpp->vcp_npfx > 1)
printf("Next match difficulty: %s (%d prefixes)\n", printf("Next match difficulty: %s (%ld prefixes)\n",
dbuf, vcpp->vcp_npfx); dbuf, vcpp->vcp_npfx);
else else
printf("Difficulty: %s\n", dbuf); printf("Difficulty: %s\n", dbuf);
}
vcpp->vcp_chance = atof(dbuf); vcpp->vcp_chance = atof(dbuf);
OPENSSL_free(dbuf); OPENSSL_free(dbuf);
} }
@ -1283,6 +1332,9 @@ vg_prefix_context_new(int addrtype, int privtype)
if (vcpp) { if (vcpp) {
vcpp->vcp_addrtype = addrtype; vcpp->vcp_addrtype = addrtype;
vcpp->vcp_privtype = privtype; vcpp->vcp_privtype = privtype;
vcpp->vcp_npfx = 0;
vcpp->vcp_npfx_start = 0;
vcpp->vcp_found = 0;
avl_root_init(&vcpp->vcp_avlroot); avl_root_init(&vcpp->vcp_avlroot);
BN_init(&vcpp->vcp_difficulty); BN_init(&vcpp->vcp_difficulty);
pthread_mutex_init(&vcpp->vcp_lock, NULL); pthread_mutex_init(&vcpp->vcp_lock, NULL);
@ -1301,7 +1353,8 @@ vg_prefix_context_add_patterns(vg_prefix_context_t *vcpp,
BIGNUM bntmp, bntmp2, bntmp3; BIGNUM bntmp, bntmp2, bntmp3;
BIGNUM *ranges[4]; BIGNUM *ranges[4];
int ret = 0; int ret = 0;
int i, npfx, fail; int i, fail;
unsigned long npfx;
char *dbuf; char *dbuf;
bnctx = BN_CTX_new(); bnctx = BN_CTX_new();
@ -1373,7 +1426,7 @@ vg_prefix_context_add_patterns(vg_prefix_context_t *vcpp,
BN_add(&bntmp2, &vcpp->vcp_difficulty, &bntmp); BN_add(&bntmp2, &vcpp->vcp_difficulty, &bntmp);
BN_copy(&vcpp->vcp_difficulty, &bntmp2); BN_copy(&vcpp->vcp_difficulty, &bntmp2);
if (verbose) { if (verbose > 1) {
BN_clear(&bntmp2); BN_clear(&bntmp2);
BN_set_bit(&bntmp2, 192); BN_set_bit(&bntmp2, 192);
BN_div(&bntmp3, NULL, &bntmp2, &bntmp, bnctx); BN_div(&bntmp3, NULL, &bntmp2, &bntmp, bnctx);
@ -1385,7 +1438,8 @@ vg_prefix_context_add_patterns(vg_prefix_context_t *vcpp,
} }
} }
vcpp->vcp_npfx = npfx; vcpp->vcp_npfx += npfx;
vcpp->vcp_npfx_start += npfx;
if (avl_root_empty(&vcpp->vcp_avlroot)) { if (avl_root_empty(&vcpp->vcp_avlroot)) {
printf("No prefix patterns to search\n"); printf("No prefix patterns to search\n");
@ -1509,8 +1563,6 @@ generate_address_prefix(vg_prefix_context_t *vcpp)
pthread_mutex_lock(&vcpp->vcp_lock); pthread_mutex_lock(&vcpp->vcp_lock);
vp = vg_prefix_avl_search(&vcpp->vcp_avlroot, &bntarg); vp = vg_prefix_avl_search(&vcpp->vcp_avlroot, &bntarg);
if (vp) { if (vp) {
printf("\n");
if (npoints) { if (npoints) {
BN_clear(&bntmp); BN_clear(&bntmp);
BN_set_word(&bntmp, npoints); BN_set_word(&bntmp, npoints);
@ -1529,8 +1581,12 @@ generate_address_prefix(vg_prefix_context_t *vcpp)
vcpp->vcp_addrtype, vcpp->vcp_addrtype,
vcpp->vcp_privtype); vcpp->vcp_privtype);
vcpp->vcp_found++;
if (remove_on_match) {
/* Subtract the range from the difficulty */ /* Subtract the range from the difficulty */
vg_prefix_range_sum(vp, &bntarg, &bntmp, &bntmp2); vg_prefix_range_sum(vp, &bntarg,
&bntmp, &bntmp2);
BN_sub(&bntmp, &vcpp->vcp_difficulty, &bntarg); BN_sub(&bntmp, &vcpp->vcp_difficulty, &bntarg);
BN_copy(&vcpp->vcp_difficulty, &bntmp); BN_copy(&vcpp->vcp_difficulty, &bntmp);
@ -1543,9 +1599,13 @@ generate_address_prefix(vg_prefix_context_t *vcpp)
&bntmp2, &bntmp2,
bnctx); bnctx);
} }
}
if (++c >= 20000) { if (++c >= 20000) {
output_timing(c, &tvstart, vcpp->vcp_chance); output_timing(c, &tvstart,
vcpp->vcp_found,
remove_on_match ? vcpp->vcp_npfx_start : 0,
vcpp->vcp_chance);
c = 0; c = 0;
} }
@ -1572,8 +1632,10 @@ typedef struct _vg_regex_context_s {
const char **vcr_regex_pat; const char **vcr_regex_pat;
int vcr_addrtype; int vcr_addrtype;
int vcr_privtype; int vcr_privtype;
int vcr_nres; unsigned long long vcr_found;
int vcr_nalloc; unsigned long vcr_nres;
unsigned long vcr_nres_start;
unsigned long vcr_nalloc;
pthread_rwlock_t vcr_lock; pthread_rwlock_t vcr_lock;
} vg_regex_context_t; } vg_regex_context_t;
@ -1585,8 +1647,10 @@ vg_regex_context_new(int addrtype, int privtype)
vcrp = (vg_regex_context_t *) malloc(sizeof(*vcrp)); vcrp = (vg_regex_context_t *) malloc(sizeof(*vcrp));
if (vcrp) { if (vcrp) {
vcrp->vcr_regex = NULL; vcrp->vcr_regex = NULL;
vcrp->vcr_found = 0;
vcrp->vcr_nalloc = 0; vcrp->vcr_nalloc = 0;
vcrp->vcr_nres = 0; vcrp->vcr_nres = 0;
vcrp->vcr_nres_start = 0;
vcrp->vcr_addrtype = addrtype; vcrp->vcr_addrtype = addrtype;
vcrp->vcr_privtype = privtype; vcrp->vcr_privtype = privtype;
pthread_rwlock_init(&vcrp->vcr_lock, NULL); pthread_rwlock_init(&vcrp->vcr_lock, NULL);
@ -1600,7 +1664,7 @@ vg_regex_context_add_patterns(vg_regex_context_t *vcrp,
{ {
const char *pcre_errptr; const char *pcre_errptr;
int pcre_erroffset; int pcre_erroffset;
int i, nres, count; unsigned long i, nres, count;
void **mem; void **mem;
if (!npatterns) if (!npatterns)
@ -1663,6 +1727,7 @@ vg_regex_context_add_patterns(vg_regex_context_t *vcrp,
if (nres == vcrp->vcr_nres) if (nres == vcrp->vcr_nres)
return 0; return 0;
vcrp->vcr_nres_start += (nres - vcrp->vcr_nres);
vcrp->vcr_nres = nres; vcrp->vcr_nres = nres;
return 1; return 1;
} }
@ -1842,8 +1907,6 @@ generate_address_regex(vg_regex_context_t *vcrp)
continue; continue;
} }
printf("\n");
if (npoints) { if (npoints) {
BN_clear(&bntmp); BN_clear(&bntmp);
BN_set_word(&bntmp, npoints); BN_set_word(&bntmp, npoints);
@ -1861,6 +1924,9 @@ generate_address_regex(vg_regex_context_t *vcrp)
output_match(pkey, vcrp->vcr_regex_pat[i], output_match(pkey, vcrp->vcr_regex_pat[i],
vcrp->vcr_addrtype, vcrp->vcr_privtype); vcrp->vcr_addrtype, vcrp->vcr_privtype);
vcrp->vcr_found++;
if (remove_on_match) {
pcre_free(vcrp->vcr_regex[i]); pcre_free(vcrp->vcr_regex[i]);
if (vcrp->vcr_regex_extra[i]) if (vcrp->vcr_regex_extra[i])
pcre_free(vcrp->vcr_regex_extra[i]); pcre_free(vcrp->vcr_regex_extra[i]);
@ -1869,15 +1935,19 @@ generate_address_regex(vg_regex_context_t *vcrp)
if (!nres) if (!nres)
goto out; goto out;
vcrp->vcr_regex[i] = vcrp->vcr_regex[nres]; vcrp->vcr_regex[i] = vcrp->vcr_regex[nres];
vcrp->vcr_regex_extra[i] = vcrp->vcr_regex_extra[nres]; vcrp->vcr_regex_extra[i] =
vcrp->vcr_regex_pat[i] = vcrp->vcr_regex_pat[nres]; vcrp->vcr_regex_extra[nres];
vcrp->vcr_regex_pat[i] =
vcrp->vcr_regex_pat[nres];
vcrp->vcr_nres = nres; vcrp->vcr_nres = nres;
}
printf("Regular expressions: %d\n", nres);
} }
if (++c >= 10000) { if (++c >= 10000) {
output_timing(c, &tvstart, 0.0); output_timing(c, &tvstart,
vcrp->vcr_found,
remove_on_match ? vcrp->vcr_nres_start : 0,
0.0);
c = 0; c = 0;
} }
@ -2002,7 +2072,7 @@ start_threads(void *(*func)(void *), void *arg, int nthreads)
} }
} }
if (verbose) { if (verbose > 1) {
printf("Using %d worker thread(s)\n", nthreads); printf("Using %d worker thread(s)\n", nthreads);
} }
@ -2021,7 +2091,7 @@ usage(const char *name)
{ {
printf( printf(
"Vanitygen %s\n" "Vanitygen %s\n"
"Usage: %s [-vriNT] [-t <threads>] [-f <filename>|-] [<pattern>...]\n" "Usage: %s [-vqrikNT] [-t <threads>] [-f <filename>|-] [<pattern>...]\n"
"Generates a bitcoin receiving address matching <pattern>, and outputs the\n" "Generates a bitcoin receiving address matching <pattern>, and outputs the\n"
"address and associated private key. The private key may be stored in a safe\n" "address and associated private key. The private key may be stored in a safe\n"
"location or imported into a bitcoin client to spend any balance received on\n" "location or imported into a bitcoin client to spend any balance received on\n"
@ -2030,14 +2100,17 @@ usage(const char *name)
"\n" "\n"
"Options:\n" "Options:\n"
"-v Verbose output\n" "-v Verbose output\n"
"-q Quiet output\n"
"-r Use regular expression match instead of prefix\n" "-r Use regular expression match instead of prefix\n"
" (Feasibility of expression is not checked)\n" " (Feasibility of expression is not checked)\n"
"-i Case-insensitive prefix search\n" "-i Case-insensitive prefix search\n"
"-k Keep pattern and continue search after finding a match\n"
"-N Generate namecoin address\n" "-N Generate namecoin address\n"
"-T Generate bitcoin testnet address\n" "-T Generate bitcoin testnet address\n"
"-t <threads> Set number of worker threads (Default: number of CPUs)\n" "-t <threads> Set number of worker threads (Default: number of CPUs)\n"
"-f <file> File containing list of patterns, one per line\n" "-f <file> File containing list of patterns, one per line\n"
" (Use \"-\" as the file name for stdin)\n", " (Use \"-\" as the file name for stdin)\n"
"-o <file> Write pattern matches to <file>\n",
version, name); version, name);
} }
@ -2056,10 +2129,13 @@ main(int argc, char **argv)
void *(*thread_func)(void *) = NULL; void *(*thread_func)(void *) = NULL;
void *thread_arg = NULL; void *thread_arg = NULL;
while ((opt = getopt(argc, argv, "vriNTt:h?f:")) != -1) { while ((opt = getopt(argc, argv, "vqrikNTt:h?f:o:")) != -1) {
switch (opt) { switch (opt) {
case 'v': case 'v':
verbose = 1; verbose = 2;
break;
case 'q':
verbose = 0;
break; break;
case 'r': case 'r':
regex = 1; regex = 1;
@ -2067,6 +2143,9 @@ main(int argc, char **argv)
case 'i': case 'i':
caseinsensitive = 1; caseinsensitive = 1;
break; break;
case 'k':
remove_on_match = 0;
break;
case 'N': case 'N':
addrtype = 52; addrtype = 52;
break; break;
@ -2097,6 +2176,13 @@ main(int argc, char **argv)
} }
} }
break; break;
case 'o':
if (result_file) {
printf("Multiple output files specified\n");
return 1;
}
result_file = optarg;
break;
default: default:
usage(argv[0]); usage(argv[0]);
return 1; return 1;
@ -2112,6 +2198,8 @@ main(int argc, char **argv)
printf("Failed to load pattern file\n"); printf("Failed to load pattern file\n");
return 1; return 1;
} }
if (fp != stdin)
fclose(fp);
} else { } else {
if (optind >= argc) { if (optind >= argc) {
@ -2127,8 +2215,8 @@ main(int argc, char **argv)
vcrp = vg_regex_context_new(addrtype, privtype); vcrp = vg_regex_context_new(addrtype, privtype);
if (!vg_regex_context_add_patterns(vcrp, patterns, npatterns)) if (!vg_regex_context_add_patterns(vcrp, patterns, npatterns))
return 1; return 1;
if (vcrp->vcr_nres > 1) if ((verbose > 0) && (vcrp->vcr_nres > 1))
printf("Regular expressions: %d\n", vcrp->vcr_nres); printf("Regular expressions: %ld\n", vcrp->vcr_nres);
thread_func = (void *(*)(void*)) generate_address_regex; thread_func = (void *(*)(void*)) generate_address_regex;
thread_arg = vcrp; thread_arg = vcrp;

Loading…
Cancel
Save