Browse Source

Add oclvanityminer. Move OpenCL engine code to oclengine.c.

master
samr7 12 years ago
parent
commit
4700be088f
  1. 11
      Makefile
  2. 31
      Makefile.Win32
  3. 18
      keyconv.c
  4. 2591
      oclengine.c
  5. 35
      oclengine.h
  6. 2534
      oclvanitygen.c
  7. 748
      oclvanityminer.c
  8. 169
      pattern.c
  9. 48
      pattern.h
  10. 8
      vanitygen.c
  11. 23
      winglue.c

11
Makefile

@ -1,16 +1,21 @@ @@ -1,16 +1,21 @@
LIBS=-lpcre -lcrypto -lm -lpthread
CFLAGS=-ggdb -O3 -Wall
OBJS=vanitygen.o oclvanitygen.o keyconv.o pattern.o util.o
PROGS=vanitygen keyconv
OBJS=vanitygen.o oclvanitygen.o oclvanityminer.o oclengine.o keyconv.o pattern.o util.o
PROGS=vanitygen oclvanitygen oclvanityminer keyconv
most: vanitygen keyconv
all: $(PROGS)
vanitygen: vanitygen.o pattern.o util.o
$(CC) $^ -o $@ $(CFLAGS) $(LIBS)
oclvanitygen: oclvanitygen.o pattern.o util.o
oclvanitygen: oclvanitygen.o oclengine.o pattern.o util.o
$(CC) $^ -o $@ $(CFLAGS) $(LIBS) -lOpenCL
oclvanityminer: oclvanityminer.o oclengine.o pattern.o util.o
$(CC) $^ -o $@ $(CFLAGS) $(LIBS) -lOpenCL -lcurl
keyconv: keyconv.o util.o
$(CC) $^ -o $@ $(CFLAGS) $(LIBS)

31
Makefile.Win32

@ -2,29 +2,42 @@ CC = cl @@ -2,29 +2,42 @@ CC = cl
OPENSSL_DIR = C:\OpenSSL-Win32
PTHREADS_DIR = C:\pthreads-w32-2-8-0-release
PCRE_DIR = C:\pcre-7.9-src
CURL_DIR = C:\curl-7.26.0-x86\builds\libcurl-release-static-ssl-static-ipv6-sspi
OPENCL_DIR = "C:\Program Files (x86)\AMD APP"
OPENCL_INCLUDE = /I$(OPENCL_DIR)\include
OPENCL_LIBS = $(OPENCL_DIR)\lib\x86\OpenCL.lib
CFLAGS = /D_WIN32 /DPTW32_STATIC_LIB /DPCRE_STATIC /I$(OPENSSL_DIR)\include /I$(PTHREADS_DIR) /I$(PCRE_DIR)
LIBS = $(OPENSSL_DIR)\lib\libeay32.lib $(PTHREADS_DIR)\pthreadVC2.lib $(PCRE_DIR)\pcre.lib ws2_32.lib
OBJS = vanitygen.obj oclvanitygen.obj keyconv.obj pattern.obj util.obj winglue.obj
CURL_INCLUDE = /I$(CURL_DIR)\include /DCURL_STATICLIB
CURL_LIBS = $(CURL_DIR)\lib\libcurl_a.lib
CFLAGS_BASE = /D_WIN32 /DPTW32_STATIC_LIB /DPCRE_STATIC /I$(OPENSSL_DIR)\inc32 /I$(PTHREADS_DIR) /I$(PCRE_DIR) /Ox /Zi
CFLAGS = $(CFLAGS_BASE) /GL
LIBS = $(OPENSSL_DIR)\out32\libeay32.lib $(PTHREADS_DIR)\pthreadVC2.lib $(PCRE_DIR)\pcre.lib ws2_32.lib user32.lib advapi32.lib gdi32.lib /LTCG /DEBUG
OBJS = vanitygen.obj oclvanitygen.obj oclengine.obj oclvanityminer.obj keyconv.obj pattern.obj util.obj winglue.obj
all: vanitygen.exe
all: vanitygen.exe keyconv.exe
vanitygen.exe: vanitygen.obj pattern.obj util.obj winglue.obj
link /nologo /out:$@ $** $(LIBS)
oclvanitygen.exe: oclvanitygen.obj pattern.obj util.obj winglue.obj
link /nologo /out:$@ $** $(LIBS) $(OPENCL_LIBS)
oclvanitygen.exe: oclvanitygen.obj oclengine.obj pattern.obj util.obj winglue.obj
link /nologo /out:$@ $** $(LIBS) $(OPENCL_LIBS) $(CURL_LIBS)
oclvanityminer.exe: oclvanityminer.obj oclengine.obj pattern.obj util.obj winglue.obj
link /nologo /out:$@ $** $(LIBS) $(OPENCL_LIBS) $(CURL_LIBS)
keyconv.exe: keyconv.obj util.obj winglue.obj
link /nologo /out:$@ $** $(LIBS) $(OPENCL_LIBS)
link /nologo /out:$@ $** $(LIBS)
.c.obj:
@$(CC) /nologo $(CFLAGS) /c /Tp$< /Fo$@
oclengine.obj: oclengine.c
@$(CC) /nologo $(CFLAGS_BASE) $(OPENCL_INCLUDE) /c /Tpoclengine.c /Fo$@
oclvanitygen.obj: oclvanitygen.c
@$(CC) /nologo $(CFLAGS) $(OPENCL_INCLUDE) /c /Tpoclvanitygen.c /Fo$@
@$(CC) /nologo $(CFLAGS_BASE) /c /Tpoclvanitygen.c /Fo$@
oclvanityminer.obj: oclvanityminer.c
@$(CC) /nologo $(CFLAGS_BASE) $(CURL_INCLUDE) /c /Tpoclvanityminer.c /Fo$@
clean:
del vanitygen.exe $(OBJS)
del vanitygen.exe oclvanitygen.exe oclvanityminer.exe keyconv.exe $(OBJS)

18
keyconv.c

@ -28,7 +28,8 @@ usage(const char *progname) @@ -28,7 +28,8 @@ usage(const char *progname)
"-8 Output key in PKCS#8 form\n"
"-e Encrypt output key, prompt for password\n"
"-E <password> Encrypt output key with <password> (UNSAFE)\n"
"-c <key> Combine private key parts to make complete private key",
"-c <key> Combine private key parts to make complete private key\n"
"-v Verbose output\n",
version, progname);
}
@ -47,10 +48,11 @@ main(int argc, char **argv) @@ -47,10 +48,11 @@ main(int argc, char **argv)
int privtype, addrtype;
int pkcs8 = 0;
int pass_prompt = 0;
int verbose = 0;
int opt;
int res;
while ((opt = getopt(argc, argv, "8E:ec:")) != -1) {
while ((opt = getopt(argc, argv, "8E:ec:v")) != -1) {
switch (opt) {
case '8':
pkcs8 = 1;
@ -75,6 +77,9 @@ main(int argc, char **argv) @@ -75,6 +77,9 @@ main(int argc, char **argv)
case 'c':
key2_in = optarg;
break;
case 'v':
verbose = 1;
break;
default:
usage(argv[0]);
return 1;
@ -149,6 +154,15 @@ main(int argc, char **argv) @@ -149,6 +154,15 @@ main(int argc, char **argv)
default: addrtype = 0; break;
}
if (verbose) {
unsigned char *pend = (unsigned char *) pbuf;
res = i2o_ECPublicKey(pkey, &pend);
fprintf(stderr, "Pubkey (hex): ");
dumphex((unsigned char *)pbuf, res);
fprintf(stderr, "Privkey (hex): ");
dumpbn(EC_KEY_get0_private_key(pkey));
}
if (pkcs8) {
res = vg_pkcs8_encode_privkey(pbuf, sizeof(pbuf),
pkey, pass_in);

2591
oclengine.c

File diff suppressed because it is too large Load Diff

35
oclengine.h

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
/*
* Vanitygen, vanity bitcoin address generator
* Copyright (C) 2011 <samr7@cs.washington.edu>
*
* Vanitygen is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Vanitygen 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Vanitygen. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (__VG_OCLENGINE_H__)
#define __VG_OCLENGINE_H__
#include "pattern.h"
typedef struct _vg_ocl_context_s vg_ocl_context_t;
extern vg_ocl_context_t *vg_ocl_context_new(
vg_context_t *vcp, int platformidx, int deviceidx,
int safe_mode, int verify,
int worksize, int nthreads, int nrows, int ncols,
int invsize);
extern void vg_ocl_context_free(vg_ocl_context_t *vocp);
extern void *vg_opencl_loop(void *vocp);
#endif /* !defined (__VG_OCLENGINE_H__) */

2534
oclvanitygen.c

File diff suppressed because it is too large Load Diff

748
oclvanityminer.c

@ -0,0 +1,748 @@ @@ -0,0 +1,748 @@
/*
* Vanitygen, vanity bitcoin address generator
* Copyright (C) 2011 <samr7@cs.washington.edu>
*
* Vanitygen is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Vanitygen 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Vanitygen. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <pthread.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
#include <curl/curl.h>
#include "oclengine.h"
#include "pattern.h"
#include "util.h"
const char *version = "0.17";
const int debug = 0;
typedef struct workitem_s {
const char *pattern;
const char *comment;
EC_POINT *pubkey;
int addrtype;
double difficulty;
double reward;
double value;
} workitem_t;
typedef struct server_request_s {
int request_status;
const EC_GROUP *group;
char *part_buf;
size_t part_off;
size_t part_end;
size_t part_size;
workitem_t **items;
int nitems;
int nalloc;
} server_request_t;
void
server_workitem_free(workitem_t *wip)
{
if (wip->pubkey)
EC_POINT_free(wip->pubkey);
free(wip);
}
static workitem_t *
server_workitem_new(server_request_t *reqp,
const char *pfx, const char *pubkey_s,
const char *addrtype_s, const char *reward_s,
const char *comment)
{
workitem_t *wip;
EC_POINT *pubkey;
int addrtype;
double reward;
double difficulty;
addrtype = atoi(addrtype_s);
if ((addrtype < 0) || (addrtype > 255))
return NULL;
reward = strtod(reward_s, NULL);
if (reward < 0.0)
return NULL;
difficulty = vg_prefix_get_difficulty(addrtype, pfx);
if (difficulty == 0.0)
return NULL;
pubkey = EC_POINT_hex2point(reqp->group, pubkey_s, NULL, NULL);
if (pubkey == NULL)
return NULL;
wip = (workitem_t *) malloc(sizeof(*wip) +
strlen(pfx) +
strlen(comment) + 2);
memset(wip, 0, sizeof(*wip));
wip->pattern = (char *) (wip + 1);
strcpy((char *)wip->pattern, pfx);
wip->comment = wip->pattern + (strlen(wip->pattern) + 1);
strcpy((char *) wip->comment, comment);
wip->pubkey = pubkey;
wip->addrtype = addrtype;
wip->difficulty = difficulty;
wip->reward = reward;
wip->value = (reward * 1000000.0 * 3600.0) / difficulty;
return wip;
}
static int
server_workitem_ptr_comp(const void *pa, const void *pb)
{
workitem_t *a = *(workitem_t **) pa, *b = *(workitem_t **) pb;
return (a->value > b->value) ? -1 : ((a->value < b->value) ? 1 : 0);
}
typedef struct server_context_s {
EC_KEY *dummy_key;
const char *url;
const char *credit_addr;
char *getwork;
char *submit;
int verbose;
} server_context_t;
static int
server_workitem_equal(server_context_t *ctxp, workitem_t *a, workitem_t *b)
{
if (strcmp(a->pattern, b->pattern))
return 0;
if (EC_POINT_cmp(EC_KEY_get0_group(ctxp->dummy_key),
a->pubkey, b->pubkey, NULL))
return 0;
return 1;
}
void
server_context_free(server_context_t *ctxp)
{
if (ctxp->dummy_key)
EC_KEY_free(ctxp->dummy_key);
if (ctxp->getwork)
free(ctxp->getwork);
if (ctxp->submit)
free(ctxp->submit);
free(ctxp);
}
server_context_t *
server_context_new(const char *url, const char *credit_addr)
{
server_context_t *ctxp;
int urllen = strlen(url);
int addrlen = strlen(credit_addr);
ctxp = (server_context_t *)
malloc(sizeof(*ctxp) + urllen + addrlen + 2);
memset(ctxp, 0, sizeof(*ctxp));
ctxp->url = (const char *) (ctxp + 1);
ctxp->credit_addr = (const char *) (ctxp->url + urllen + 1);
strcpy((char *) ctxp->url, url);
strcpy((char *) ctxp->credit_addr, credit_addr);
ctxp->dummy_key = vg_exec_context_new_key();
ctxp->getwork = (char *) malloc(urllen + 9);
ctxp->submit = (char *) malloc(urllen + 7);
if (url[urllen - 1] == '/') {
snprintf(ctxp->getwork, urllen + 9, "%sgetWork", url);
snprintf(ctxp->submit, urllen + 7, "%ssolve", url);
} else {
snprintf(ctxp->getwork, urllen + 9, "%s/getWork", url);
snprintf(ctxp->submit, urllen + 7, "%s/solve", url);
}
return ctxp;
}
int
server_workitem_add(server_request_t *reqp, workitem_t *wip)
{
int nalloc;
if ((reqp->nitems + 1) >= reqp->nalloc) {
nalloc = reqp->nalloc * 2;
if (nalloc == 0)
nalloc = 16;
if (nalloc > 65536)
return -1;
reqp->items = (workitem_t **)
realloc(reqp->items, nalloc * sizeof(*reqp->items));
if (reqp->items == NULL)
return -1;
reqp->nalloc = nalloc;
}
reqp->items[reqp->nitems++] = wip;
return 0;
}
static int
server_body_reader(const char *buf, size_t elemsize, size_t len, void *param)
{
server_request_t *reqp = (server_request_t *) param;
char *line, *sep, *pfx, *pubkey_s, *addrtype_s, *reward_s, *comment;
workitem_t *wip;
if (!len)
return 0;
if ((reqp->part_size < (reqp->part_end + len)) &&
(reqp->part_off > 0)) {
memmove(reqp->part_buf,
reqp->part_buf + reqp->part_off,
reqp->part_end - reqp->part_off);
reqp->part_end -= reqp->part_off;
reqp->part_off = 0;
}
if (reqp->part_size < (reqp->part_end + len)) {
if (reqp->part_size == 0)
reqp->part_size = 4096;
while (reqp->part_size < (reqp->part_end + len)) {
reqp->part_size *= 2;
if (reqp->part_size > (1024*1024)) {
fprintf(stderr, "Line too long from server");
reqp->request_status = 0;
return -1;
}
}
reqp->part_buf = (char *) realloc(reqp->part_buf,
reqp->part_size);
if (!reqp->part_buf) {
fprintf(stderr, "Out of memory");
return -1;
}
}
memcpy(reqp->part_buf + reqp->part_end, buf, len);
reqp->part_end += len;
line = reqp->part_buf;
while (1) {
sep = strchr(line, '\n');
if (!sep)
break;
pfx = line;
*sep = '\0';
line = sep + 1;
sep = strchr(pfx, ':');
if (!sep)
goto bad_line;
*sep = '\0'; sep += 1;
pubkey_s = sep;
sep = strchr(sep, ':');
if (!sep)
goto bad_line;
*sep = '\0'; sep += 1;
addrtype_s = sep;
sep = strchr(sep, ':');
if (!sep)
goto bad_line;
*sep = '\0'; sep += 1;
reward_s = sep;
sep = strchr(sep, ';');
if (!sep)
goto bad_line;
*sep = '\0'; sep += 1;
comment = sep;
wip = server_workitem_new(reqp, pfx, pubkey_s, addrtype_s,
reward_s, comment);
if (!wip)
goto bad_line;
if (server_workitem_add(reqp, wip)) {
server_workitem_free(wip);
goto bad_line;
}
continue;
bad_line:
;
}
reqp->part_off = line - reqp->part_buf;
if (reqp->part_off == reqp->part_end) {
reqp->part_off = 0;
reqp->part_end = 0;
}
return len;
}
void
dump_work(workitem_t **workarray)
{
workitem_t *wip;
int i;
printf("Available bounties:\n");
for (i = 0; workarray[i] != NULL; i++) {
wip = workarray[i];
printf("Pattern: \"%s\" Reward: %f Value: %f BTC/MkeyHr\n",
wip->pattern,
wip->reward,
wip->value);
}
}
void
free_work_array(workitem_t **workarray, workitem_t *except)
{
int i;
if (workarray) {
for (i = 0; workarray[i] != NULL; i++) {
if (workarray[i] != except)
server_workitem_free(workarray[i]);
}
free(workarray);
}
}
workitem_t **
server_context_getwork(server_context_t *ctxp)
{
CURLcode res;
server_request_t *reqp;
CURL *creq;
reqp = (server_request_t *) malloc(sizeof(*reqp));
memset(reqp, 0, sizeof(*reqp));
reqp->group = EC_KEY_get0_group(ctxp->dummy_key);
creq = curl_easy_init();
if (curl_easy_setopt(creq, CURLOPT_URL, ctxp->getwork) ||
curl_easy_setopt(creq, CURLOPT_VERBOSE, ctxp->verbose > 1) ||
curl_easy_setopt(creq, CURLOPT_WRITEFUNCTION,
server_body_reader) ||
curl_easy_setopt(creq, CURLOPT_WRITEDATA, reqp)) {
fprintf(stderr, "Failed to set up libcurl\n");
exit(1);
}
res = curl_easy_perform(creq);
if (res != CURLE_OK) {
fprintf(stderr, "Get work request failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(creq);
free_work_array(reqp->items, NULL);
return NULL;
}
if (reqp->items) {
qsort(reqp->items, reqp->nitems, sizeof(*(reqp->items)),
server_workitem_ptr_comp);
reqp->items[reqp->nitems] = NULL;
}
curl_easy_cleanup(creq);
return reqp->items;
}
int
server_context_submit_solution(server_context_t *ctxp,
workitem_t *work,
const char *privkey)
{
char urlbuf[8192];
char *pubhex;
CURL *creq;
CURLcode res;
pubhex = EC_POINT_point2hex(EC_KEY_get0_group(ctxp->dummy_key),
work->pubkey,
POINT_CONVERSION_UNCOMPRESSED,
NULL);
snprintf(urlbuf, sizeof(urlbuf),
"%s?key=%s%%3A%s&privateKey=%s&bitcoinAddress=%s",
ctxp->submit,
work->pattern,
pubhex,
privkey,
ctxp->credit_addr);
OPENSSL_free(pubhex);
creq = curl_easy_init();
if (curl_easy_setopt(creq, CURLOPT_URL, urlbuf) ||
curl_easy_setopt(creq, CURLOPT_VERBOSE, ctxp->verbose > 1) ||
curl_easy_setopt(creq, CURLOPT_POST, 1)) {
fprintf(stderr, "Failed to set up libcurl\n");
exit(1);
}
res = curl_easy_perform(creq);
if (res != CURLE_OK) {
fprintf(stderr, "Submission failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(creq);
return -1;
}
curl_easy_cleanup(creq);
return 0;
}
static pthread_mutex_t soln_lock;
static pthread_cond_t soln_cond;
static char *soln_pattern = NULL;
static char *soln_private_key = NULL;
void
free_soln()
{
if (soln_pattern) {
free(soln_pattern);
soln_pattern = NULL;
}
if (soln_private_key) {
OPENSSL_free(soln_private_key);
soln_private_key = NULL;
}
}
void
output_match_work_complete(vg_context_t *vcp, EC_KEY *pkey, const char *pattern)
{
vg_output_match_console(vcp, pkey, pattern);
pthread_mutex_lock(&soln_lock);
free_soln();
soln_pattern = strdup(pattern);
soln_private_key = BN_bn2hex(EC_KEY_get0_private_key(pkey));
/* Signal the generator to stop */
vcp->vc_halt = 1;
/* Wake up the main thread, if it's sleeping */
pthread_cond_broadcast(&soln_cond);
pthread_mutex_unlock(&soln_lock);
}
int
check_solution(server_context_t *scp, workitem_t *wip)
{
int res = 0;
pthread_mutex_lock(&soln_lock);
if (soln_private_key != NULL) {
assert(!strcmp(soln_pattern, wip->pattern));
server_context_submit_solution(scp, wip, soln_private_key);
free_soln();
res = 1;
}
pthread_mutex_unlock(&soln_lock);
return res;
}
void
usage(const char *name)
{
fprintf(stderr,
"oclVanityMiner %s (" OPENSSL_VERSION_TEXT ")\n"
"Usage: %s -u <URL> -a <credit address>\n"
"Organized vanity address mining client using OpenCL. Contacts the specified\n"
"bounty pool server, downloads a list of active bounties, and attempts to\n"
"generate the address with the best difficulty to reward ratio. Maintains\n"
"contact with the bounty pool server and periodically refreshes the bounty\n"
"list.\n"
"\n"
"Options:\n"
"-u <URL> Bounty pool URL\n"
"-a <address> Credit address for completed work\n"
"-i <interval> Set server polling interval in seconds (default 90)\n"
"-v Verbose output\n"
"-q Quiet output\n"
"-p <platform> Select OpenCL platform\n"
"-d <device> Select OpenCL device\n"
"-S Safe mode, disable OpenCL loop unrolling optimizations\n"
"-w <worksize> Set work items per thread in a work unit\n"
"-t <threads> Set target thread count per multiprocessor\n"
"-g <x>x<y> Set grid size\n"
"-b <invsize> Set modular inverse ops per thread\n"
"-V Enable kernel/OpenCL/hardware verification (SLOW)\n",
version, name);
}
int
main(int argc, char **argv)
{
const char *url = NULL;
const char *credit_addr = NULL;
int opt;
int platformidx = -1, deviceidx = -1;
char *pend;
int verbose = 1;
int interval = 90;
int nthreads = 0;
int worksize = 0;
int nrows = 0, ncols = 0;
int invsize = 0;
int verify_mode = 0;
int safe_mode = 0;
vg_context_t *vcp = NULL;
vg_ocl_context_t *vocp = NULL;
int res;
int thread_started = 0;
pthread_t thread;
workitem_t *active_wip = NULL;
server_context_t *scp = NULL;
workitem_t *wip = NULL, **wipa;
int wip_index;
int was_sleeping = 0;
struct timeval tv;
struct timespec sleepy;
pthread_mutex_init(&soln_lock, NULL);
pthread_cond_init(&soln_cond, NULL);
if (argc == 1) {
usage(argv[0]);
return 1;
}
while ((opt = getopt(argc, argv,
"u:a:vqp:d:w:t:g:b:VSh?i:")) != -1) {
switch (opt) {
case 'u':
url = optarg;
break;
case 'a':
credit_addr = optarg;
break;
case 'v':
verbose = 2;
break;
case 'q':
verbose = 0;
break;
case 'i':
interval = atoi(optarg);
if (interval < 60) {
fprintf(stderr,
"Invalid interval '%s'\n", optarg);
return 1;
}
case 'p':
platformidx = atoi(optarg);
break;
case 'd':
deviceidx = atoi(optarg);
break;
case 'w':
worksize = atoi(optarg);
if (worksize == 0) {
fprintf(stderr,
"Invalid work size '%s'\n", optarg);
return 1;
}
break;
case 't':
nthreads = atoi(optarg);
if (nthreads == 0) {
fprintf(stderr,
"Invalid thread count '%s'\n", optarg);
return 1;
}
break;
case 'g':
nrows = 0;
ncols = strtol(optarg, &pend, 0);
if (pend && *pend == 'x') {
nrows = strtol(pend+1, NULL, 0);
}
if (!nrows || !ncols) {
fprintf(stderr,
"Invalid grid size '%s'\n", optarg);
return 1;
}
break;
case 'b':
invsize = atoi(optarg);
if (!invsize) {
fprintf(stderr,
"Invalid modular inverse size '%s'\n",
optarg);
return 1;
}
if (invsize & (invsize - 1)) {
fprintf(stderr,
"Modular inverse size must be "
"a power of 2\n");
return 1;
}
break;
case 'V':
verify_mode = 1;
break;
case 'S':
safe_mode = 1;
break;
default:
usage(argv[0]);
return 1;
}
}
#if OPENSSL_VERSION_NUMBER < 0x10000000L
/* Complain about older versions of OpenSSL */
if (verbose > 0) {
fprintf(stderr,
"WARNING: Built with " OPENSSL_VERSION_TEXT "\n"
"WARNING: Use OpenSSL 1.0.0d+ for best performance\n");
}
#endif
curl_easy_init();
vcp = vg_prefix_context_new(0, 128, 0);
vcp->vc_verbose = verbose;
vcp->vc_output_match = output_match_work_complete;
vcp->vc_output_timing = vg_output_timing_console;
if (!url) {
fprintf(stderr, "ERROR: No server URL specified\n");
return 1;
}
if (!credit_addr) {
fprintf(stderr, "ERROR: No reward address specified\n");
return 1;
}
if (!vg_b58_decode_check(credit_addr, NULL, 0)) {
fprintf(stderr, "ERROR: Invalid reward address specified\n");
return 1;
}
scp = server_context_new(url, credit_addr);
scp->verbose = verbose;
wipa = NULL;
while (1) {
if (!wipa) {
wipa = server_context_getwork(scp);
wip_index = 0;
}
if (wipa) {
wip = wipa[wip_index];
if (wip)
wip_index += 1;
} else
wip = NULL;
/* If the work item is the same as the one we're executing,
keep it */
if (wip && active_wip &&
server_workitem_equal(scp, active_wip, wip))
wip = active_wip;
if (thread_started && (!active_wip || (wip != active_wip))) {
/* If a thread is running, stop it */
vcp->vc_halt = 1;
pthread_join(thread, NULL);
thread_started = 0;
vcp->vc_halt = 0;
if (active_wip) {
check_solution(scp, active_wip);
active_wip = NULL;
}
vg_context_clear_all_patterns(vcp);
}
if (!wip) {
if (!was_sleeping) {
fprintf(stderr,
"No work available, sleeping\n");
was_sleeping = 1;
}
} else if (!active_wip) {
was_sleeping = 0;
fprintf(stderr,
"Searching for pattern: \"%s\" "
"Reward: %f Value: %f BTC/MkeyHr\n",
wip->pattern,
wip->reward,
wip->value);
vcp->vc_addrtype = wip->addrtype;
vcp->vc_pubkey_base = wip->pubkey;
if (!vg_context_add_patterns(vcp, &wip->pattern, 1))
return 1;
assert(vcp->vc_npatterns);
if (!vocp) {
vocp = vg_ocl_context_new(vcp,
platformidx, deviceidx,
safe_mode, verify_mode,
worksize, nthreads, nrows,
ncols, invsize);
if (!vocp)
return 1;
}
res = pthread_create(&thread, NULL,
vg_opencl_loop, vocp);
thread_started = 1;
active_wip = wip;
}
/* Wait for something to happen */
gettimeofday(&tv, NULL);
sleepy.tv_sec = tv.tv_sec;
sleepy.tv_nsec = tv.tv_usec * 1000;
sleepy.tv_sec += interval;
pthread_mutex_lock(&soln_lock);
if (!soln_private_key)
res = pthread_cond_timedwait(&soln_cond,
&soln_lock, &sleepy);
pthread_mutex_unlock(&soln_lock);
if (res == 0) {
if (check_solution(scp, active_wip))
active_wip = NULL;
}
else if (res == ETIMEDOUT) {
if (wipa) {
free_work_array(wipa, active_wip);
wipa = NULL;
}
}
}
return 0;
}

169
pattern.c

@ -141,20 +141,13 @@ typedef struct _timing_info_s { @@ -141,20 +141,13 @@ typedef struct _timing_info_s {
int
vg_output_timing(vg_context_t *vcp, int cycle, struct timeval *last)
{
static unsigned long long total = 0, prevfound = 0, sincelast = 0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static timing_info_t *timing_head = NULL;
pthread_t me;
struct timeval tvnow, tv;
timing_info_t *tip, *mytip;
unsigned long long rate, myrate = 0, mytime;
double count, prob, time, targ;
char linebuf[80];
char *unit;
int rem, p, i;
const double targs[] = { 0.5, 0.75, 0.8, 0.9, 0.95, 1.0 };
unsigned long long rate, myrate = 0, mytime, total, sincelast;
int p, i;
/* Compute the rate */
gettimeofday(&tvnow, NULL);
@ -167,7 +160,8 @@ vg_output_timing(vg_context_t *vcp, int cycle, struct timeval *last) @@ -167,7 +160,8 @@ vg_output_timing(vg_context_t *vcp, int cycle, struct timeval *last)
pthread_mutex_lock(&mutex);
me = pthread_self();
for (tip = timing_head, mytip = NULL; tip != NULL; tip = tip->ti_next) {
for (tip = vcp->vc_timing_head, mytip = NULL;
tip != NULL; tip = tip->ti_next) {
if (pthread_equal(tip->ti_thread, me)) {
mytip = tip;
p = ((tip->ti_hist_last + 1) % timing_hist_size);
@ -190,9 +184,9 @@ vg_output_timing(vg_context_t *vcp, int cycle, struct timeval *last) @@ -190,9 +184,9 @@ vg_output_timing(vg_context_t *vcp, int cycle, struct timeval *last)
}
if (!mytip) {
mytip = (timing_info_t *) malloc(sizeof(*tip));
mytip->ti_next = timing_head;
mytip->ti_next = vcp->vc_timing_head;
mytip->ti_thread = me;
timing_head = mytip;
vcp->vc_timing_head = mytip;
mytip->ti_hist_last = 0;
mytip->ti_hist_time[0] = mytime;
mytip->ti_hist_work[0] = cycle;
@ -205,20 +199,47 @@ vg_output_timing(vg_context_t *vcp, int cycle, struct timeval *last) @@ -205,20 +199,47 @@ vg_output_timing(vg_context_t *vcp, int cycle, struct timeval *last)
rate += myrate;
}
total += cycle;
if (prevfound != vcp->vc_found) {
prevfound = vcp->vc_found;
sincelast = 0;
vcp->vc_timing_total += cycle;
if (vcp->vc_timing_prevfound != vcp->vc_found) {
vcp->vc_timing_prevfound = vcp->vc_found;
vcp->vc_timing_sincelast = 0;
}
sincelast += cycle;
count = sincelast;
vcp->vc_timing_sincelast += cycle;
if (mytip != timing_head) {
if (mytip != vcp->vc_timing_head) {
pthread_mutex_unlock(&mutex);
return myrate;
}
total = vcp->vc_timing_total;
sincelast = vcp->vc_timing_sincelast;
pthread_mutex_unlock(&mutex);
vcp->vc_output_timing(vcp, sincelast, rate, total);
return myrate;
}
static void
vg_timing_info_free(vg_context_t *vcp)
{
timing_info_t *tp;
while (vcp->vc_timing_head != NULL) {
tp = vcp->vc_timing_head;
vcp->vc_timing_head = tp->ti_next;
free(tp);
}
}
void
vg_output_timing_console(vg_context_t *vcp, double count,
unsigned long long rate, unsigned long long total)
{
double prob, time, targ;
char *unit;
char linebuf[80];
int rem, p, i;
const double targs[] = { 0.5, 0.75, 0.8, 0.9, 0.95, 1.0 };
targ = rate;
unit = "key/s";
if (targ > 1000) {
@ -314,11 +335,10 @@ vg_output_timing(vg_context_t *vcp, int cycle, struct timeval *last) @@ -314,11 +335,10 @@ vg_output_timing(vg_context_t *vcp, int cycle, struct timeval *last)
}
printf("\r%s", linebuf);
fflush(stdout);
return myrate;
}
void
vg_output_match(vg_context_t *vcp, EC_KEY *pkey, const char *pattern)
vg_output_match_console(vg_context_t *vcp, EC_KEY *pkey, const char *pattern)
{
unsigned char key_buf[512], *pend;
char addr_buf[64], addr2_buf[64];
@ -386,6 +406,7 @@ vg_output_match(vg_context_t *vcp, EC_KEY *pkey, const char *pattern) @@ -386,6 +406,7 @@ vg_output_match(vg_context_t *vcp, EC_KEY *pkey, const char *pattern)
printf("Privkey (ASN1): ");
dumphex(key_buf, len);
}
}
if (!vcp->vc_result_file || (vcp->vc_verbose > 0)) {
@ -420,20 +441,26 @@ vg_output_match(vg_context_t *vcp, EC_KEY *pkey, const char *pattern) @@ -420,20 +441,26 @@ vg_output_match(vg_context_t *vcp, EC_KEY *pkey, const char *pattern)
}
void
vg_context_free(vg_context_t *vcp)
{
vg_timing_info_free(vcp);
vcp->vc_free(vcp);
}
int
vg_context_add_patterns(vg_context_t *vcp,
char ** const patterns, int npatterns)
const char ** const patterns, int npatterns)
{
return vcp->vc_add_patterns(vcp, patterns, npatterns);
}
void
vg_context_clear_all_patterns(vg_context_t *vcp)
{
vcp->vc_clear_all_patterns(vcp);
}
int
vg_context_hash160_sort(vg_context_t *vcp, void *buf)
{
@ -699,6 +726,21 @@ out: @@ -699,6 +726,21 @@ out:
return ret;
}
static void
free_ranges(BIGNUM **ranges)
{
BN_free(ranges[0]);
BN_free(ranges[1]);
ranges[0] = NULL;
ranges[1] = NULL;
if (ranges[2]) {
BN_free(ranges[2]);
BN_free(ranges[3]);
ranges[2] = NULL;
ranges[3] = NULL;
}
}
/*
* AVL tree implementation
*/
@ -1364,7 +1406,7 @@ typedef struct _vg_prefix_context_s { @@ -1364,7 +1406,7 @@ typedef struct _vg_prefix_context_s {
} vg_prefix_context_t;
static void
vg_prefix_context_free(vg_context_t *vcp)
vg_prefix_context_clear_all_patterns(vg_context_t *vcp)
{
vg_prefix_context_t *vcpp = (vg_prefix_context_t *) vcp;
vg_prefix_t *vp;
@ -1378,6 +1420,17 @@ vg_prefix_context_free(vg_context_t *vcp) @@ -1378,6 +1420,17 @@ vg_prefix_context_free(vg_context_t *vcp)
}
assert(npfx_left == vcpp->base.vc_npatterns);
vcpp->base.vc_npatterns = 0;
vcpp->base.vc_npatterns_start = 0;
vcpp->base.vc_found = 0;
BN_clear(&vcpp->vcp_difficulty);
}
static void
vg_prefix_context_free(vg_context_t *vcp)
{
vg_prefix_context_t *vcpp = (vg_prefix_context_t *) vcp;
vg_prefix_context_clear_all_patterns(vcp);
BN_clear_free(&vcpp->vcp_difficulty);
free(vcpp);
}
@ -1407,7 +1460,7 @@ vg_prefix_context_next_difficulty(vg_prefix_context_t *vcpp, @@ -1407,7 +1460,7 @@ vg_prefix_context_next_difficulty(vg_prefix_context_t *vcpp,
static int
vg_prefix_context_add_patterns(vg_context_t *vcp,
char ** const patterns, int npatterns)
const char ** const patterns, int npatterns)
{
vg_prefix_context_t *vcpp = (vg_prefix_context_t *) vcp;
prefix_case_iter_t caseiter;
@ -1556,6 +1609,47 @@ vg_prefix_context_add_patterns(vg_context_t *vcp, @@ -1556,6 +1609,47 @@ vg_prefix_context_add_patterns(vg_context_t *vcp,
return ret;
}
double
vg_prefix_get_difficulty(int addrtype, const char *pattern)
{
BN_CTX *bnctx;
BIGNUM result, bntmp;
BIGNUM *ranges[4];
char *dbuf;
int ret;
double diffret = 0.0;
bnctx = BN_CTX_new();
BN_init(&result);
BN_init(&bntmp);
ret = get_prefix_ranges(addrtype,
pattern, ranges, bnctx);
if (ret == 0) {
BN_sub(&bntmp, ranges[1], ranges[0]);
BN_add(&result, &result, &bntmp);
if (ranges[2]) {
BN_sub(&bntmp, ranges[3], ranges[2]);
BN_add(&result, &result, &bntmp);
}
free_ranges(ranges);
BN_clear(&bntmp);
BN_set_bit(&bntmp, 192);
BN_div(&result, NULL, &bntmp, &result, bnctx);
dbuf = BN_bn2dec(&result);
diffret = strtod(dbuf, NULL);
OPENSSL_free(dbuf);
}
BN_clear_free(&result);
BN_clear_free(&bntmp);
BN_CTX_free(bnctx);
return diffret;
}
static int
vg_prefix_test(vg_exec_context_t *vxcp)
@ -1579,7 +1673,8 @@ research: @@ -1579,7 +1673,8 @@ research:
goto research;
vg_exec_context_consolidate_key(vxcp);
vg_output_match(&vcpp->base, vxcp->vxc_key, vp->vp_pattern);
vcpp->base.vc_output_match(&vcpp->base, vxcp->vxc_key,
vp->vp_pattern);
vcpp->base.vc_found++;
@ -1673,6 +1768,8 @@ vg_prefix_context_new(int addrtype, int privtype, int caseinsensitive) @@ -1673,6 +1768,8 @@ vg_prefix_context_new(int addrtype, int privtype, int caseinsensitive)
vcpp->base.vc_chance = 0.0;
vcpp->base.vc_free = vg_prefix_context_free;
vcpp->base.vc_add_patterns = vg_prefix_context_add_patterns;
vcpp->base.vc_clear_all_patterns =
vg_prefix_context_clear_all_patterns;
vcpp->base.vc_test = vg_prefix_test;
vcpp->base.vc_hash160_sort = vg_prefix_hash160_sort;
avl_root_init(&vcpp->vcp_avlroot);
@ -1695,7 +1792,7 @@ typedef struct _vg_regex_context_s { @@ -1695,7 +1792,7 @@ typedef struct _vg_regex_context_s {
static int
vg_regex_context_add_patterns(vg_context_t *vcp,
char ** const patterns, int npatterns)
const char ** const patterns, int npatterns)
{
vg_regex_context_t *vcrp = (vg_regex_context_t *) vcp;
const char *pcre_errptr;
@ -1770,7 +1867,7 @@ vg_regex_context_add_patterns(vg_context_t *vcp, @@ -1770,7 +1867,7 @@ vg_regex_context_add_patterns(vg_context_t *vcp,
}
static void
vg_regex_context_free(vg_context_t *vcp)
vg_regex_context_clear_all_patterns(vg_context_t *vcp)
{
vg_regex_context_t *vcrp = (vg_regex_context_t *) vcp;
int i;
@ -1779,6 +1876,16 @@ vg_regex_context_free(vg_context_t *vcp) @@ -1779,6 +1876,16 @@ vg_regex_context_free(vg_context_t *vcp)
pcre_free(vcrp->vcr_regex_extra[i]);
pcre_free(vcrp->vcr_regex[i]);
}
vcrp->base.vc_npatterns = 0;
vcrp->base.vc_npatterns_start = 0;
vcrp->base.vc_found = 0;
}
static void
vg_regex_context_free(vg_context_t *vcp)
{
vg_regex_context_t *vcrp = (vg_regex_context_t *) vcp;
vg_regex_context_clear_all_patterns(vcp);
if (vcrp->vcr_nalloc)
free(vcrp->vcr_regex);
free(vcrp);
@ -1860,8 +1967,8 @@ restart_loop: @@ -1860,8 +1967,8 @@ restart_loop:
goto restart_loop;
vg_exec_context_consolidate_key(vxcp);
vg_output_match(&vcrp->base, vxcp->vxc_key,
vcrp->vcr_regex_pat[i]);
vcrp->base.vc_output_match(&vcrp->base, vxcp->vxc_key,
vcrp->vcr_regex_pat[i]);
vcrp->base.vc_found++;
if (vcrp->base.vc_remove_on_match) {
@ -1902,6 +2009,8 @@ vg_regex_context_new(int addrtype, int privtype) @@ -1902,6 +2009,8 @@ vg_regex_context_new(int addrtype, int privtype)
vcrp->base.vc_chance = 0.0;
vcrp->base.vc_free = vg_regex_context_free;
vcrp->base.vc_add_patterns = vg_regex_context_add_patterns;
vcrp->base.vc_clear_all_patterns =
vg_regex_context_clear_all_patterns;
vcrp->base.vc_test = vg_regex_test;
vcrp->base.vc_hash160_sort = NULL;
vcrp->vcr_regex = NULL;

48
pattern.h

@ -56,16 +56,24 @@ extern void vg_exec_context_consolidate_key(vg_exec_context_t *vxcp); @@ -56,16 +56,24 @@ extern void vg_exec_context_consolidate_key(vg_exec_context_t *vxcp);
extern void vg_exec_context_calc_address(vg_exec_context_t *vxcp);
extern EC_KEY *vg_exec_context_new_key(void);
/* Implementation-specific lock/unlock/consolidate */
extern void vg_exec_downgrade_lock(vg_exec_context_t *vxcp);
extern int vg_exec_upgrade_lock(vg_exec_context_t *vxcp);
typedef void (*vg_free_func_t)(vg_context_t *);
typedef int (*vg_add_pattern_func_t)(vg_context_t *,
char ** const patterns, int npatterns);
const char ** const patterns,
int npatterns);
typedef void (*vg_clear_all_patterns_func_t)(vg_context_t *);
typedef int (*vg_test_func_t)(vg_exec_context_t *);
typedef int (*vg_hash160_sort_func_t)(vg_context_t *vcp, void *buf);
typedef void (*vg_output_error_func_t)(vg_context_t *vcp, const char *info);
typedef void (*vg_output_match_func_t)(vg_context_t *vcp, EC_KEY *pkey,
const char *pattern);
typedef void (*vg_output_timing_func_t)(vg_context_t *vcp, double count,
unsigned long long rate,
unsigned long long total);
enum vg_format {
VCF_PUBKEY,
@ -84,28 +92,50 @@ struct _vg_context_s { @@ -84,28 +92,50 @@ struct _vg_context_s {
const char *vc_key_protect_pass;
int vc_remove_on_match;
int vc_verbose;
vg_free_func_t vc_free;
vg_add_pattern_func_t vc_add_patterns;
vg_test_func_t vc_test;
vg_hash160_sort_func_t vc_hash160_sort;
enum vg_format vc_format;
int vc_pubkeytype;
EC_POINT *vc_pubkey_base;
int vc_halt;
/* Internal methods */
vg_free_func_t vc_free;
vg_add_pattern_func_t vc_add_patterns;
vg_clear_all_patterns_func_t vc_clear_all_patterns;
vg_test_func_t vc_test;
vg_hash160_sort_func_t vc_hash160_sort;
/* Performance related members */
unsigned long long vc_timing_total;
unsigned long long vc_timing_prevfound;
unsigned long long vc_timing_sincelast;
struct _timing_info_s *vc_timing_head;
/* External methods */
vg_output_error_func_t vc_output_error;
vg_output_match_func_t vc_output_match;
vg_output_timing_func_t vc_output_timing;
};
extern void vg_context_free(vg_context_t *vcp);
extern int vg_context_add_patterns(vg_context_t *vcp,
char ** const patterns, int npatterns);
const char ** const patterns, int npatterns);
extern void vg_context_clear_all_patterns(vg_context_t *vcp);
extern int vg_context_hash160_sort(vg_context_t *vcp, void *buf);
extern vg_context_t *vg_prefix_context_new(int addrtype, int privtype,
int caseinsensitive);
extern double vg_prefix_get_difficulty(int addrtype, const char *pattern);
extern vg_context_t *vg_regex_context_new(int addrtype, int privtype);
extern int vg_output_timing(vg_context_t *vcp, int cycle, struct timeval *last);
extern void vg_output_match(vg_context_t *vcp, EC_KEY *pkey,
const char *pattern);
extern void vg_output_match_console(vg_context_t *vcp, EC_KEY *pkey,
const char *pattern);
extern void vg_output_timing_console(vg_context_t *vcp, double count,
unsigned long long rate,
unsigned long long total);
#endif /* !defined (__VG_PATTERN_H__) */

8
vanitygen.c

@ -280,7 +280,7 @@ vg_thread_loop(void *arg) @@ -280,7 +280,7 @@ vg_thread_loop(void *arg)
hash_len = 65;
}
while (1) {
while (!vcp->vc_halt) {
if (++npoints >= rekey_at) {
pthread_mutex_lock(&vg_thread_lock);
/* Generate a new random private key */
@ -704,7 +704,11 @@ main(int argc, char **argv) @@ -704,7 +704,11 @@ main(int argc, char **argv)
vcp->vc_pubkeytype = pubkeytype;
vcp->vc_pubkey_base = pubkey_base;
if (!vg_context_add_patterns(vcp, patterns, npatterns))
vcp->vc_output_match = vg_output_match_console;
vcp->vc_output_timing = vg_output_timing_console;
if (!vg_context_add_patterns(vcp, (const char ** const) patterns,
npatterns))
return 1;
if (!vcp->vc_npatterns) {

23
winglue.c

@ -73,11 +73,9 @@ count_processors(void) @@ -73,11 +73,9 @@ count_processors(void)
* struct timeval compatibility for Win32
*/
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif
#define TIMESPEC_TO_FILETIME_OFFSET \
( ((unsigned __int64) 27111902 << 32) + \
(unsigned __int64) 3577643008 )
int
gettimeofday(struct timeval *tv, struct timezone *tz)
@ -88,14 +86,13 @@ gettimeofday(struct timeval *tv, struct timezone *tz) @@ -88,14 +86,13 @@ gettimeofday(struct timeval *tv, struct timezone *tz)
if (NULL != tv) {
GetSystemTimeAsFileTime(&ft);
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
tmpres -= DELTA_EPOCH_IN_MICROSECS;
tmpres /= 10;
tv->tv_sec = (long)(tmpres / 1000000UL);
tv->tv_usec = (long)(tmpres % 1000000UL);
tv->tv_sec = (int) ((*(unsigned __int64 *) &ft -
TIMESPEC_TO_FILETIME_OFFSET) /
10000000);
tv->tv_usec = (int) ((*(unsigned __int64 *) &ft -
TIMESPEC_TO_FILETIME_OFFSET -
((unsigned __int64) tv->tv_sec *
(unsigned __int64) 10000000)) / 10);
}
return 0;

Loading…
Cancel
Save