<p>You can change</p>

<pre><code>        switch (test_func(vxcp)) {
        case 1:
            npoints = 0;
            rekey_at = 0;
            i = nbatch;
            break;
        case 2:
            goto out;
        default:
            break;
        }
</code></pre>

<p>to</p>

<pre><code>        switch (test_func(vxcp)) {
        case 2:
            goto out;
        default:
            npoints = 0;
            rekey_at = 0;
            i = nbatch;
            break;
        }
</code></pre>

<p>You can also replace the <code>test_func</code> with a function in which you check if the public key is the one you're looking for. Since you'll always use the <code>-k</code> option, you can replace the <code>switch</code> with</p>

<pre><code>        test_func(vxcp);
        npoints = 0;
        rekey_at = 0;
        i = nbatch;
</code></pre>

CC BY-SA 4.0
2019-01-02T11:15:32.443Z
OK, i just change it & it work but look like the program doesn't use 100% CPU anymore & it only generate few thoundsands private key per seconds. Do you have any suggestion?
Dan Minh Toan
CC BY-SA 4.0
2019-01-02T11:25:12.540Z
the check public key seems to work perfectly fine though
Dan Minh Toan
CC BY-SA 4.0
2019-01-02T12:21:40.283Z
You should add "array of private keys" in "execute context" (vxcp) in pattern.h. Above the part that contains  `/* Common case`, you should call the RNG for all of the points and set the points to the public keys. You should also remove the condition `if (++npoints >= rekey_at) {` and the else part associated with it. In `vg_exec_context_consolidate_key`, which is called by the test_func, youshould change the pointer to private key so that it points to your array you added to execute_context in pattern.h and takes the index of pk.Lastly, increasing `ptarraysize` should improveperfomnc.GoodLuck
MCCCS
CC BY-SA 4.0
2019-01-03T03:41:04.693Z
You’re welcome. Let me know if you’re stuck or it doesn’t work.
MCCCS
CC BY-SA 4.0
2019-02-13T11:11:31.473Z
hi, it's me again. I want to modify the same fuction on GPU, can you suggest some idea to run it on oclvanitygen without multiply key? Ididn't have expericnce with opencl. The core function was in "oclengine.c" but there're no "if (++npoints >= rekey_at)" so it was hard to know where to edit the code
Dan Minh Toan
CC BY-SA 4.0
2019-02-13T13:10:30.933Z
@DanMinhToan Is this what you're looking for: https://github.com/samr7/vanitygen/blob/master/oclengine.c#L1906
MCCCS
CC BY-SA 4.0
2019-02-13T14:37:23.330Z
yes, it has the same key generator but the multiply funtion was different
Dan Minh Toan
CC BY-SA 4.0
2019-02-25T07:14:15.093Z
i tried to reduce the rekey_max value to 1 to make sure it use the seed every time generate a new privkey(normally, it'll search 100000000 keys before use the seed again), turn out it decrease the performance as well (about 85keys/s), if i change from a single EC_key to key array, there're error show up. How can i make it use only rng seed but maximize the performance at the same time?
Dan Minh Toan
CC BY-SA 4.0
2019-01-02T11:06:09.967Z
2019-01-02T11:06:09.967Z
MCCCS
<p>I just using vanitygen recently &amp; figure how to create address from a given hex private key, this is my code</p>

<pre><code>while (!vcp-&gt;vc_halt) {
         if (++npoints &gt;= rekey_at) {
            vg_exec_context_upgrade_lock(vxcp);
            /* Generate a new random private key */
            BIGNUM start;
            BIGNUM *res;
            BN_init(&amp;start);
            res = &amp;start;
            BN_hex2bn(&amp;res, "3B1BCC5A67F38853810972B1DA8A67148FAD78C6CD6F22B2C823D141BE59C81C"); //Set up hex private key
            vg_set_privkey(res, pkey);
            //EC_KEY_generate_key(pkey); default code
            if (vcp-&gt;vc_privkey_prefix_length &gt; 0) {
                BIGNUM *pkbn = BN_dup(EC_KEY_get0_private_key(pkey));
                unsigned char pkey_arr[32];
                assert(BN_bn2bin(pkbn, pkey_arr) &lt; 33);
                memcpy((char *)pkey_arr, vcp-&gt;vc_privkey_prefix, vcp-&gt;vc_privkey_prefix_length);
                for (int i = 0; i &lt; vcp-&gt;vc_privkey_prefix_length / 2; i++) {
                    int k = pkey_arr[i];
                    pkey_arr[i] = pkey_arr[vcp-&gt;vc_privkey_prefix_length - 1 - i];
                    pkey_arr[vcp-&gt;vc_privkey_prefix_length - 1 - i] = k;
                }
                BN_bin2bn(pkey_arr, 32, pkbn);
                EC_KEY_set_private_key(pkey, pkbn);

                EC_POINT *origin = EC_POINT_new(pgroup);
                EC_POINT_mul(pgroup, origin, pkbn, NULL, NULL, vxcp-&gt;vxc_bnctx);
                EC_KEY_set_public_key(pkey, origin);
            }
            npoints = 0;

            /* Determine rekey interval */
            EC_GROUP_get_order(pgroup, vxcp-&gt;vxc_bntmp,
                vxcp-&gt;vxc_bnctx);
            BN_sub(vxcp-&gt;vxc_bntmp2,
                vxcp-&gt;vxc_bntmp,
                EC_KEY_get0_private_key(pkey));
            rekey_at = BN_get_word(vxcp-&gt;vxc_bntmp2);
            if ((rekey_at == 0xffffffffL) || (rekey_at &gt; rekey_max))
                rekey_at = rekey_max;
            assert(rekey_at &gt; 0);

            EC_POINT_copy(ppnt[0], EC_KEY_get0_public_key(pkey));
            vg_exec_context_downgrade_lock(vxcp);

            npoints++;
            vxcp-&gt;vxc_delta = 0;

            if (vcp-&gt;vc_pubkey_base)
                EC_POINT_add(pgroup,
                    ppnt[0],
                    ppnt[0],
                    vcp-&gt;vc_pubkey_base,
                    vxcp-&gt;vxc_bnctx);

            for (nbatch = 1;
                (nbatch &lt; ptarraysize) &amp;&amp; (npoints &lt; rekey_at);
                nbatch++, npoints++) {
                EC_POINT_add(pgroup,
                    ppnt[nbatch],
                    ppnt[nbatch - 1],
                    pgen, vxcp-&gt;vxc_bnctx);
            }

         }
        else {
            /*
             * Common case
             *
             * EC_POINT_add() can skip a few multiplies if
             * one or both inputs are affine (Z_is_one).
             * This is the case for every point in ppnt, as
             * well as pbatchinc.
             */
            assert(nbatch == ptarraysize);
            for (nbatch = 0;
                (nbatch &lt; ptarraysize) &amp;&amp; (npoints &lt; rekey_at);
                nbatch++, npoints++) {
                EC_POINT_add(pgroup,
                    ppnt[nbatch],
                    ppnt[nbatch],
                    pbatchinc,
                    vxcp-&gt;vxc_bnctx);
            }
        }

        /*
         * The single most expensive operation performed in this
         * loop is modular inversion of ppnt-&gt;Z.  There is an
         * algorithm implemented in OpenSSL to do batched inversion
         * that only does one actual BN_mod_inverse(), and saves
         * a _lot_ of time.
         *
         * To take advantage of this, we batch up a few points,
         * and feed them to EC_POINTs_make_affine() below.
         */

        EC_POINTs_make_affine(pgroup, nbatch, ppnt, vxcp-&gt;vxc_bnctx);

        for (i = 0; i &lt; nbatch; i++, vxcp-&gt;vxc_delta++) {
            /* Hash the public key */
            len = EC_POINT_point2oct(pgroup, ppnt[i],
                (vcp-&gt;vc_compressed) ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED,
                eckey_buf,
                (vcp-&gt;vc_compressed) ? 33 : 65,
                vxcp-&gt;vxc_bnctx);
            assert(len == 65 || len == 33);

            SHA256(hash_buf, hash_len, hash1);
            RIPEMD160(hash1, sizeof(hash1), &amp;vxcp-&gt;vxc_binres[1]);

            switch (test_func(vxcp)) {
            case 1:
                npoints = 0;
                rekey_at = 0;
                i = nbatch;
                break;
            case 2:
                goto out;
            default:
                break;
            }
        }

        c += i;
        if (c &gt;= output_interval) {
            output_interval = vg_output_timing(vcp, c, &amp;tvstart);
            if (output_interval &gt; 250000)
                output_interval = 250000;
            c = 0;
        }

        vg_exec_context_yield(vxcp);
    }
</code></pre>

<p>I try to run the program &amp; expect result like this</p>

<blockquote>
  <p>Address: 14m54cDDgC96ptqTz66431PoD7f6CPmsHE </p>
  
  <p>Priv key: 5JGKRxEqgMQU1SC86uJHt6Bp6hBZCyea6PHfWvPDpuMsYFiiQpE</p>
</blockquote>

<p>Technically it work when i generate a single address everytime but when i use <code>-k</code> to keep it generating it turn up lots of random address not as i intented to</p>

<blockquote>
  <p>Address: 18b9xT21uxvmwU31whAcnW7ytag7Qdz5wH</p>
  
  <p>Address: 1LKHy9Y8pMTsNdwfZXYexKegNvXc6UTm9C</p>
  
  <p>Address: 16esSUcRDz1um1bBWhBynSvmJUqXZWTHd7</p>
  
  <p>....</p>
</blockquote>

<p>What i understand is it keep multiply value of my given key to make new address &amp; it take a while to reach loop to set private key in <code>pkey</code> again. Is there any way that i can skip this part &amp; make it generate pure new private key everytime. I intened to replace this with my own random key generator to recover my paper wallet, thank you</p>

<development><vanitygen>
Modify vanitygen to generate from massive amount of given private key
Dan Minh Toan
# Modify vanitygen to generate from massive amount of given private key

(Asked by: username_0 on 2019-01-02)

I just using vanitygen recently & figure how to create address from a given hex private key, this is my code

```
while (!vcp->vc_halt) {
         if (++npoints >= rekey_at) {
            vg_exec_context_upgrade_lock(vxcp);
            /* Generate a new random private key */
            BIGNUM start;
            BIGNUM *res;
            BN_init(&start);
            res = &start;
            BN_hex2bn(&res, "3B1BCC5A67F38853810972B1DA8A67148FAD78C6CD6F22B2C823D141BE59C81C"); //Set up hex private key
            vg_set_privkey(res, pkey);
            //EC_KEY_generate_key(pkey); default code
            if (vcp->vc_privkey_prefix_length > 0) {
                BIGNUM *pkbn = BN_dup(EC_KEY_get0_private_key(pkey));
                unsigned char pkey_arr[32];
                assert(BN_bn2bin(pkbn, pkey_arr) < 33);
                memcpy((char *)pkey_arr, vcp->vc_privkey_prefix, vcp->vc_privkey_prefix_length);
                for (int i = 0; i < vcp->vc_privkey_prefix_length / 2; i++) {
                    int k = pkey_arr[i];
                    pkey_arr[i] = pkey_arr[vcp->vc_privkey_prefix_length - 1 - i];
                    pkey_arr[vcp->vc_privkey_prefix_length - 1 - i] = k;
                }
                BN_bin2bn(pkey_arr, 32, pkbn);
                EC_KEY_set_private_key(pkey, pkbn);

                EC_POINT *origin = EC_POINT_new(pgroup);
                EC_POINT_mul(pgroup, origin, pkbn, NULL, NULL, vxcp->vxc_bnctx);
                EC_KEY_set_public_key(pkey, origin);
            }
            npoints = 0;

            /* Determine rekey interval */
            EC_GROUP_get_order(pgroup, vxcp->vxc_bntmp,
                vxcp->vxc_bnctx);
            BN_sub(vxcp->vxc_bntmp2,
                vxcp->vxc_bntmp,
                EC_KEY_get0_private_key(pkey));
            rekey_at = BN_get_word(vxcp->vxc_bntmp2);
            if ((rekey_at == 0xffffffffL) || (rekey_at > rekey_max))
                rekey_at = rekey_max;
            assert(rekey_at > 0);

            EC_POINT_copy(ppnt[0], EC_KEY_get0_public_key(pkey));
            vg_exec_context_downgrade_lock(vxcp);

            npoints++;
            vxcp->vxc_delta = 0;

            if (vcp->vc_pubkey_base)
                EC_POINT_add(pgroup,
                    ppnt[0],
                    ppnt[0],
                    vcp->vc_pubkey_base,
                    vxcp->vxc_bnctx);

            for (nbatch = 1;
                (nbatch < ptarraysize) && (npoints < rekey_at);
                nbatch++, npoints++) {
                EC_POINT_add(pgroup,
                    ppnt[nbatch],
                    ppnt[nbatch - 1],
                    pgen, vxcp->vxc_bnctx);
            }

         }
        else {
            /*
             * Common case
             *
             * EC_POINT_add() can skip a few multiplies if
             * one or both inputs are affine (Z_is_one).
             * This is the case for every point in ppnt, as
             * well as pbatchinc.
             */
            assert(nbatch == ptarraysize);
            for (nbatch = 0;
                (nbatch < ptarraysize) && (npoints < rekey_at);
                nbatch++, npoints++) {
                EC_POINT_add(pgroup,
                    ppnt[nbatch],
                    ppnt[nbatch],
                    pbatchinc,
                    vxcp->vxc_bnctx);
            }
        }

        /*
         * The single most expensive operation performed in this
         * loop is modular inversion of ppnt->Z.  There is an
         * algorithm implemented in OpenSSL to do batched inversion
         * that only does one actual BN_mod_inverse(), and saves
         * a _lot_ of time.
         *
         * To take advantage of this, we batch up a few points,
         * and feed them to EC_POINTs_make_affine() below.
         */

        EC_POINTs_make_affine(pgroup, nbatch, ppnt, vxcp->vxc_bnctx);

        for (i = 0; i < nbatch; i++, vxcp->vxc_delta++) {
            /* Hash the public key */
            len = EC_POINT_point2oct(pgroup, ppnt[i],
                (vcp->vc_compressed) ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED,
                eckey_buf,
                (vcp->vc_compressed) ? 33 : 65,
                vxcp->vxc_bnctx);
            assert(len == 65 || len == 33);

            SHA256(hash_buf, hash_len, hash1);
            RIPEMD160(hash1, sizeof(hash1), &vxcp->vxc_binres[1]);

            switch (test_func(vxcp)) {
            case 1:
                npoints = 0;
                rekey_at = 0;
                i = nbatch;
                break;
            case 2:
                goto out;
            default:
                break;
            }
        }

        c += i;
        if (c >= output_interval) {
            output_interval = vg_output_timing(vcp, c, &tvstart);
            if (output_interval > 250000)
                output_interval = 250000;
            c = 0;
        }

        vg_exec_context_yield(vxcp);
    }

```

I try to run the program & expect result like this

> Address: 14m54cDDgC96ptqTz66431PoD7f6CPmsHE
>
> Priv key: 5JGKRxEqgMQU1SC86uJHt6Bp6hBZCyea6PHfWvPDpuMsYFiiQpE

Technically it work when i generate a single address everytime but when i use `-k` to keep it generating it turn up lots of random address not as i intented to

> Address: 18b9xT21uxvmwU31whAcnW7ytag7Qdz5wH
>
> Address: 1LKHy9Y8pMTsNdwfZXYexKegNvXc6UTm9C
>
> Address: 16esSUcRDz1um1bBWhBynSvmJUqXZWTHd7
>
> ....

What i understand is it keep multiply value of my given key to make new address & it take a while to reach loop to set private key in `pkey` again. Is there any way that i can skip this part & make it generate pure new private key everytime. I intened to replace this with my own random key generator to recover my paper wallet, thank you

**Tags:** development, vanitygen


---

## 1 answers

### Answer by username_1 on 2019-01-02. Score: 1 | Accepted answer

You can change

```
        switch (test_func(vxcp)) {
        case 1:
            npoints = 0;
            rekey_at = 0;
            i = nbatch;
            break;
        case 2:
            goto out;
        default:
            break;
        }

```

to

```
        switch (test_func(vxcp)) {
        case 2:
            goto out;
        default:
            npoints = 0;
            rekey_at = 0;
            i = nbatch;
            break;
        }

```

You can also replace the `test_func` with a function in which you check if the public key is the one you're looking for. Since you'll always use the `-k` option, you can replace the `switch` with

```
        test_func(vxcp);
        npoints = 0;
        rekey_at = 0;
        i = nbatch;

```

> **Comments:**
> **username_0**: OK, i just change it & it work but look like the program doesn't use 100% CPU anymore & it only generate few thoundsands private key per seconds. Do you have any suggestion?  
> **username_0**: the check public key seems to work perfectly fine though  
> **username_1**: You should add "array of private keys" in "execute context" (vxcp) in pattern.h. Above the part that contains  `/* Common case`, you should call the RNG for all of the points and set the points to the public keys. You should also remove the condition `if (++npoints >= rekey_at) {` and the else part associated with it. In `vg_exec_context_consolidate_key`, which is called by the test_func, youshould change the pointer to private key so that it points to your array you added to execute_context in pattern.h and takes the index of pk.Lastly, increasing `ptarraysize` should improveperfomnc.GoodLuck  
> **username_1**: You’re welcome. Let me know if you’re stuck or it doesn’t work.  
> **username_0**: hi, it's me again. I want to modify the same fuction on GPU, can you suggest some idea to run it on oclvanitygen without multiply key? Ididn't have expericnce with opencl. The core function was in "oclengine.c" but there're no "if (++npoints >= rekey_at)" so it was hard to know where to edit the code  
> **username_1**: @username_0 Is this what you're looking for: https://github.com/samr7/vanitygen/blob/master/oclengine.c#L1906  
> **username_0**: yes, it has the same key generator but the multiply funtion was different  
> **username_0**: i tried to reduce the rekey_max value to 1 to make sure it use the seed every time generate a new privkey(normally, it'll search 100000000 keys before use the seed again), turn out it decrease the performance as well (about 85keys/s), if i change from a single EC_key to key array, there're error show up. How can i make it use only rng seed but maximize the performance at the same time?  

---

