Post
Topic
Board Bitcoin Discussion
Re: Bitcoin puzzle transaction ~32 BTC prize to who solves it
by
nomachine
on 23/11/2023, 13:15:48 UTC
...

it would be awesome if there's a CUDA version for it.

I can give you this same script that works in C++ but you have to do the GPU part yourself.CUDA programming can be complex, and proper error handling and synchronization are crucial. Also, not all parts of your program may benefit from GPU acceleration, so it's essential to profile and optimize as needed.

puzzle66.cpp
Code:
#include <iostream>
#include <vector>
#include <iomanip>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/obj_mac.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <ctime>
#include <sstream>
#include <fstream>

// Function to convert a byte vector to a hexadecimal string
std::string bytesToHex(const std::vector<unsigned char>& bytes) {
    std::stringstream ss;
    for (unsigned char byte : bytes) {
        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
    }
    return ss.str();
}

// Function to calculate the RIPEMD160 hash of a byte vector
std::vector<unsigned char> calculateRIPEMD160(const std::vector<unsigned char>& data) {
    std::vector<unsigned char> hash(RIPEMD160_DIGEST_LENGTH);
    RIPEMD160(data.data(), data.size(), hash.data());
    return hash;
}

int main() {
    // Initialize the OpenSSL library
    if (OpenSSL_add_all_algorithms() != 1) {
        std::cerr << "OpenSSL initialization failed." << std::endl;
        return 1;
    }

    // Set the target Hash160 value (replace with your target hash)
    std::string target_hash160_hex = "20d45a6a762535700ce9e0b216e31994335db8a5";

    int puzzle = 66;   // The puzzle number (Bits)

    // Clear the console
    std::system("clear");
    std::cout << "\r\033[01;33m[+] Bytea HASH160 Search by NoMachine" << "\n";
    time_t currentTime = std::time(nullptr);
    std::cout << "\r\033[01;33m[+] " << std::ctime(&currentTime) << "\r";
    std::cout << "\r\033[01;33m[+] Puzzle: " << puzzle << "\033[0m" << std::endl;
    std::cout.flush();

    // Calculate the maximum bytes value based on the puzzle
    BIGNUM* limit_int = BN_new();
    BN_set_word(limit_int, 1);
    BN_lshift(limit_int, limit_int, puzzle);
    BN_sub_word(limit_int, 1);
    int max_bytes = (BN_num_bits(limit_int) + 7) / 8;

    // Create an EC_KEY object
    EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);

    // Calculate the SHA-256 hash of the public key
    unsigned char sha256_result[SHA256_DIGEST_LENGTH];

    // Calculate the RIPEMD160 hash of the SHA-256 hash
    std::vector<unsigned char> ripemd160_result(RIPEMD160_DIGEST_LENGTH);

    while (true) {
        // Create a 32-byte private key with 32 zeros followed by random bytes
        std::vector<unsigned char> private_key_bytes(32, 0);

        // Generate random bytes for the remaining part of the private key
        std::vector<unsigned char> random_bytes(max_bytes);
        if (RAND_bytes(random_bytes.data(), random_bytes.size()) != 1) {
            std::cerr << "Error generating random bytes." << std::endl;
            BN_free(limit_int);
            EC_KEY_free(ec_key);
            return 1;
        }

        // Append the random bytes to the private key
        std::copy(random_bytes.begin(), random_bytes.end(), private_key_bytes.begin() + 32 - max_bytes);

        // Create a BIGNUM from the private key bytes
        BIGNUM* bn_private_key = BN_bin2bn(private_key_bytes.data(), private_key_bytes.size(), NULL);

        // Set the private key in the EC_KEY object
        EC_KEY_set_private_key(ec_key, bn_private_key);

        // Compute the public key from the private key
        EC_POINT* public_key_point = EC_POINT_new(EC_KEY_get0_group(ec_key));
        EC_POINT_mul(EC_KEY_get0_group(ec_key), public_key_point, bn_private_key, NULL, NULL, NULL);

        // Convert the public key point to binary representation (compressed)
        size_t public_key_length = EC_POINT_point2oct(EC_KEY_get0_group(ec_key), public_key_point, POINT_CONVERSION_COMPRESSED, NULL, 0, NULL);
        std::vector<unsigned char> public_key_bytes(public_key_length);
        EC_POINT_point2oct(EC_KEY_get0_group(ec_key), public_key_point, POINT_CONVERSION_COMPRESSED, public_key_bytes.data(), public_key_length, NULL);

        // Check if the public key starts with "02" (compressed format)
        if (public_key_bytes[0] == 0x02) {
            SHA256(public_key_bytes.data(), public_key_bytes.size(), sha256_result);
            ripemd160_result = calculateRIPEMD160(std::vector<unsigned char>(sha256_result, sha256_result + SHA256_DIGEST_LENGTH));

            // Convert the calculated RIPEMD160 hash to a hexadecimal string
            std::string calculated_hash160_hex = bytesToHex(ripemd160_result);

            // Display the generated public key hash (Hash160) and private key
            std::string message = "\r\033[01;33m[+] Public Key Hash (Hash 160): " + calculated_hash160_hex;
            std::cout << message << "\e[?25l";
            std::cout.flush();

            // Check if the generated public key hash matches the target
            if (calculated_hash160_hex == target_hash160_hex) {
                // Get the current time
                std::time_t currentTime;
                std::time(&currentTime);
                std::tm tmStruct = *std::localtime(&currentTime);

                // Format the current time into a human-readable string
                std::stringstream timeStringStream;
                timeStringStream << std::put_time(&tmStruct, "%Y-%m-%d %H:%M:%S");
                std::string formattedTime = timeStringStream.str();

                std::cout << "\n\033[32m[+] PUZZLE SOLVED: " << formattedTime << "\033[0m" << std::endl;
                std::cout << "\r\033[32m[+] Target Public Key Hash (Hash160) found! Private Key: " << bytesToHex(private_key_bytes) << std::endl;

                // Append the private key information to a file if it matches
                std::ofstream file("KEYFOUNDKEYFOUND.txt", std::ios::app);
                if (file.is_open()) {
                    file << "\nPUZZLE SOLVED " << formattedTime;
                    file << "\nPrivate Key (hex): " << bytesToHex(private_key_bytes);
                    file << "\n--------------------------------------------------------------------------------------------------------------------------------------------";
                    file.close();
                }

                break;
            }
        }
    }

    // Free the EC_KEY and BIGNUM objects
    BN_free(limit_int);
    EC_KEY_free(ec_key);

    return 0;
}

Scripts check if the public key starts with "02" (compressed format)  and you can change to "03".

Makefile
Code:
# Makefile

# Source files
SRC = puzzle66.cpp

# Compiler and flags
CXX = g++
CXXFLAGS = -m64 -march=native -mtune=native  -mfpmath=sse -Wall -msse2 -msse3 -msse4 -msse4.1 -msse4.2 -msse4a -mavx -pthread -O3 -I.

# OpenSSL libraries
LIBS = -lssl -lcrypto

# Output executable
TARGET = puzzle66

# Default target
all: $(TARGET)

# Rule for compiling the source code
$(TARGET): $(SRC)
$(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)

# Clean target to remove generated files
clean:
rm -f $(TARGET)

.PHONY: all clean

I am running this on an AMD Ryzen 9 7950X.
It has  compiler flags for AMD which accelerate mathematical crypto functions. A similar file must be created for CUDA.
Good luck....