I'm making a Vanity address miner that generates compressed addresses, mostly because I'm bored, took an intro C++ course, and think cryptography is nifty. Feel free to call me an idiot, or encourage me. Tips and advice appreciated.
I'm using CryptoPP because VanityGen uses OpenSSL, and I wanted to make mine different. No particular reason other than that.
I'll post source code for interesting bits here, and give an idea of my progress.
Goals:
Create a working CPU miner
Create a working GPU miner
Implement getwork
Implement shares system
Profit
Progress to make:
Comparison
Modular add/multiply
Getwork
Shares/proof of work
Nifty codes:
Base58 to Hex, returns cryptopp Integer
Integer base58decode(string input)
{
int parse;
Integer key;
for(int i = 0; i < input.length(); i++)
{
parse = 0;
while(true)
{
if(input[i] == b58[parse])
{
key = (key + parse)*58;
break;
}
else
parse++;
}
}
key = key/58;
return key;
}
Integer and leading zeroes to Base58
string base58encode(Integer plain, int zeros)
{
string adr;
Integer remainder, temp;
while(plain != 0)
{
plain.Divide(remainder, temp, plain, 58);
plain = temp;
adr = b58[remainder.ConvertToLong()] + adr;
}
while(zeros)
{
adr = "1" + adr;
zeros--;
}
return adr;
}
The whole program, messy as it is.
#include <iostream>
#include <iomanip>
// CryptoPP includes
#include <cryptopp\cryptlib.h>
#include <cryptopp\filters.h>
#include <cryptopp\eccrypto.h>
#include <cryptopp\hex.h>
#include <cryptopp\osrng.h>
#include <cryptopp\sha.h>
#include <cryptopp\ripemd.h>
#include <cryptopp\integer.h>
#include <cryptopp\oids.h>
using namespace std;
using namespace CryptoPP;
string b58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
byte odd[] = {0x03};
byte eve[] = {0x02};
AutoSeededRandomPool prng;
ECDSA<ECP, SHA256>::PrivateKey Priv;
ECDSA<ECP, SHA256>::PublicKey Pub;
bool loop(byte* goal);
string digest2hex(byte* digest, int len);
byte* str2hexarr(char* in, int len);
byte* step(string raw);
string base58encode(Integer plain, int zeros);
Integer base58decode(string input);
string process(string raw);
int
main()
{
Integer loops;
byte goal[] = {0x01};
while(loop(goal) == false && loops < 800)
{
loops++;
cout << "\r" << std::dec << loops;
}
}
bool
loop(byte* goal)
{
string temp;
byte x[32];
Priv.Initialize( prng, CryptoPP::ASN1::secp256k1());
Priv.MakePublicKey(Pub);
SHA256 crunchy;
if(Pub.GetPublicElement().y.IsEven() == 0)
crunchy.Update(odd, 1);
else
crunchy.Update(eve, 1);
Pub.GetPublicElement().x.Encode(x, 32);
crunchy.Update(x,32);
byte digestA[32];
crunchy.Final(digestA);
byte digestB[20];
RIPEMD160().CalculateDigest(digestB, digestA, 32);
if(digestB[0] == goal[0])
{
cout << endl << std::hex << Priv.GetPrivateExponent();
return true;
}
else
return false;
}
string
digest2hex(byte* digest, int len)
{
string output;
HexEncoder encoder;
StringSink *SS = new StringSink(output);
encoder.Attach(SS);
encoder.Put(digest,len);
encoder.MessageEnd();
return output;
}
byte*
str2hexarr(char* in, int len)
{
for(int i = 0; in[i]; i++)
in[i] = toupper(in[i]);
byte part2[len/2];
unsigned int i, t, hn, ln;
for (t = 0,i = 0; i < len; i+=2,++t)
{
hn = in[i] > '9' ? in[i] - 'A' + 10 : in[i] - '0';
ln = in[i+1] > '9' ? in[i+1] - 'A' + 10 : in[i+1] - '0';
part2[t] = (hn << 4 ) | ln;
}
return part2;
}
byte*
step(string raw)
{
SHA256 hash;
RIPEMD160 more_hash;
byte digest[SHA256::DIGESTSIZE];
byte digest2[RIPEMD160::DIGESTSIZE];
hash.CalculateDigest(digest,(const byte *)raw.c_str(),raw.size());
more_hash.CalculateDigest(digest2, digest, SHA256::DIGESTSIZE);
Integer d = Integer(digest2, RIPEMD160::DIGESTSIZE+4);
cout << endl << std::hex << d;
cout << endl << base58encode(d, 0);
return digest2;
}
string
base58encode(Integer plain, int zeros)
{
string adr;
Integer remainder, temp;
while(plain != 0)
{
plain.Divide(remainder, temp, plain, 58);
plain = temp;
adr = b58[remainder.ConvertToLong()] + adr;
}
while(zeros)
{
adr = "1" + adr;
zeros--;
}
return adr;
}
Integer
base58decode(string input)
{
int parse;
Integer key;
for(int i = 0; i < input.length(); i++)
{
parse = 0;
while(true)
{
if(input[i] == b58[parse])
{
key = (key + parse)*58;
break;
}
else
parse++;
}
}
key = key/58;
return key;
}
string
process(string raw)
{
SHA256 hash;
RIPEMD160 more_hash;
byte digest[SHA256::DIGESTSIZE];
byte digest2[RIPEMD160::DIGESTSIZE];
byte digest2_mod[RIPEMD160::DIGESTSIZE+5];
hash.CalculateDigest(digest,(const byte *)raw.c_str(),raw.size());
more_hash.CalculateDigest(digest2, digest, SHA256::DIGESTSIZE);
digest2_mod[0]=0x00;
for(int i = 0; i<= RIPEMD160::DIGESTSIZE; i++)
digest2_mod[i+1] = digest2[i];
hash.CalculateDigest(digest,digest2_mod,RIPEMD160::DIGESTSIZE+1);
hash.CalculateDigest(digest,digest,SHA256::DIGESTSIZE);
for(int i = 0; i< 4; i++)
digest2_mod[i+RIPEMD160::DIGESTSIZE+1] = digest[i];
Integer out = Integer(digest2_mod, RIPEMD160::DIGESTSIZE+5);
int lead;
for(lead = 0; digest2_mod[lead] == 0; lead++);
string ret = base58encode(out, lead);
return ret;
}