Vanityアドレス

Vanityアドレスとは、人が読めるまたは意味のある文字列を含むアドレスのこと。 例えば、

1deconstructionxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

とかです。

アドレスは、最後にハッシュ関数を使っているので、メールアドレスのようにほしいアドレスを簡単にとることはできないです。

それで、ランダムな値から鍵生成とハッシュを繰り返して、ほしい条件を満たすアドレスがでるまで待ちます(笑)

このことをvanityアドレスマイニングというみたいです。 ざっくり言えばいわゆるブロックのマイニングと同じようなものですしね。

技術的に意味あるかは微妙ですが、遊びで1deconで始まるアドレスをマイニングしてみました。

Mastering Bitcoinにあるソースをベースに最新のlibbitcoinに合わせてちょこっといじったソースが以下です。

#include <random>
#include <bitcoin/bitcoin.hpp>

// 以下の文字列で始まる文字列を探索
const std::string search = "1decon";

// 秘密鍵の生成.
bc::ec_secret random_secret(std::default_random_engine& engine);

// 秘密鍵からビットコインアドレスを算出
std::string bitcoin_address(const bc::ec_secret& secret);

// 条件にあう文字列かどうか探索
bool match_found(const std::string& address);

int main()
{
    // 遊びなので疑似乱数生成器 "/dev/urandom"を使用
    std::random_device random;
    std::default_random_engine engine(random());

    // 見つかるまでループ
    while (true)
    {
        // ランダムな秘密鍵生成
        bc::ec_secret secret = random_secret(engine);

        // 秘密鍵からアドレスを取得
        std::string address = bitcoin_address(secret);
        // 取得したアドレスが条件に合うか判定
        if (match_found(address))
        {
            // 発見!
            std::cout << "Found vanity address! " << address << std::endl;
            std::cout << "Secret: " << bc::encode_base16(secret) << std::endl;
            return 0;
        }
    }

    return 0;
}

bc::ec_secret random_secret(std::default_random_engine& engine)
{
    bc::ec_secret secret;

    // 乱数からバイト毎に並べる
    for (uint8_t& byte: secret)
        byte = engine() % std::numeric_limits<uint8_t>::max();
    return secret;
}

std::string bitcoin_address(const bc::ec_secret& secret)
{
    // 秘密鍵&アドレス生成
    bc::wallet::ec_private private_key(secret);
    bc::wallet::payment_address payaddr(private_key);

    // エンコードして返却
    return payaddr.encoded();
}

bool match_found(const std::string& address)
{
    auto addr_it = address.begin();
    // 条件にあう文字列かを探索
    for (auto it = search.begin(); it != search.end(); ++it, ++addr_it)
        if (*it != std::tolower(*addr_it))
            return false;
    // 条件に合ったらtrue
    return true;
}

コンパイルして実行してみると

$ sudo g++ -std=gnu++11 -o vanity-miner vanity.cpp $(pkg-config --cflags --libs libbitcoin)
$ ./vanity-miner 
Found vanity address! 1DEcoNFKrnhwfke34iTpLjtzM2EdwT3wWT
Secret: c9ccea1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

30分ほどで1DEcoNから始まるアドレスが見つかってマイニング成功! まあ、使いませんけどね(笑)