Bitcoin Forum
April 03, 2026, 02:13:03 PM *
News: Latest Bitcoin Core release: 30.2 [Torrent]
 
   Home   Help Search Login Register More  
Pages: « 1 ... 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 [421] 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 ... 648 »
  Print  
Author Topic: Bitcoin puzzle transaction ~32 BTC prize to who solves it  (Read 377327 times)
Denevron
Newbie
*
Offline Offline

Activity: 121
Merit: 0


View Profile
March 30, 2025, 04:25:31 PM
 #8401

can be called a mutagen Grin

It's not that simple, but it speeds up the process, you've noticed it yourself)

you can add it to Cyclon as a new method, and there you just don’t calculate the puzzle range, but enter the key by which the bits will change, and it’s better not in random mode, but in sequential mode, because the random mode will loop and that’s it, and you will be forever, say, chasing in 30 bits, and you won’t find it, and it will be, say, in 33 bits



Code:
import time
import multiprocessing
import secp256k1 as ice
import random
from math import comb
import numpy as np

# Configuration
TARGET_ADDR = "1HsMJxNiV7TLxmoF6uJNkydxPFDog4NQum"  # Puzzle 20
BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f"  # Puzzle 19 Private Key
PUZZLE_NUM = 20
WORKERS = multiprocessing.cpu_count()

# Historical flip counts
FLIP_TABLE = {
    20:8, 21:8, 22:9, 23:9, 24:10, 25:11, 26:12, 27:13, 28:14, 29:15,
    30:16, 31:17, 32:18, 33:19, 34:20, 35:21, 36:22, 37:23, 38:24, 39:25,
    40:26, 41:27, 42:28, 43:29, 44:30, 45:31, 46:32, 47:33, 48:34, 49:35,
    50:36, 51:37, 52:38, 53:39, 54:40, 55:41, 56:42, 57:43, 58:44, 59:45,
    60:46, 61:47, 62:48, 63:49, 64:50, 65:51, 66:52, 67:53
}

def predict_flips(puzzle_num):
    """Predict flip count using linear regression with bounds"""
    if puzzle_num in FLIP_TABLE:
        return FLIP_TABLE[puzzle_num]
   
    # Linear regression
    x = np.array(list(FLIP_TABLE.keys()))
    y = np.array(list(FLIP_TABLE.values()))
    coeffs = np.polyfit(x, y, 1)
    predicted = round(coeffs[0] * puzzle_num + coeffs[1])
   
    # Apply bounds (50-60% of bits)
    bit_length = puzzle_num
    lower = max(8, int(bit_length * 0.5))
    upper = min(int(bit_length * 0.6), bit_length-5)
    return min(max(predicted, lower), upper)

def mutate_key(base_int, flip_positions):
    """Ultra-fast bit flipping using XOR mask"""
    flip_mask = sum(1 << bit for bit in flip_positions)
    return base_int ^ flip_mask

def worker(base_int, bit_length, flip_count, results, stop_event):
    checked = 0
    bit_positions = list(range(bit_length))
    start_time = time.time()
   
    while not stop_event.is_set():
        # Generate random flip positions
        flip_pos = random.sample(bit_positions, flip_count)
       
        # Create mutated key
        priv_int = mutate_key(base_int, flip_pos)
        checked += 1
       
        # Generate address
        addr = ice.privatekey_to_address(0, True, priv_int)
       
        if addr == TARGET_ADDR:
            hex_key = "%064x" % priv_int
            actual_flips = bin(base_int ^ priv_int).count('1')
            results.put((hex_key, checked, actual_flips))
            stop_event.set()
            return
           
        # Progress update
        if checked % 10000 == 0:
            elapsed = time.time() - start_time
            speed = checked/elapsed if elapsed > 0 else 0
            print(f"Checked {checked:,} | {speed:,.0f} keys/sec", end='\r')

def parallel_search():
    bit_length = PUZZLE_NUM
    base_int = int(BASE_KEY, 16)
    flip_count = predict_flips(PUZZLE_NUM)
    total_combs = comb(bit_length, flip_count)
   
    print(f"\nSearching Puzzle {PUZZLE_NUM} (256-bit)")
    print(f"Base Key: {BASE_KEY}")
    print(f"Target: {TARGET_ADDR}")
    print(f"Predicted Flip Count: {flip_count} bits")
    print(f"Total Possible Combinations: 2^{int(np.log2(total_combs)):,}")
    print(f"Using {WORKERS} workers...\n")
   
    manager = multiprocessing.Manager()
    results = manager.Queue()
    stop_event = manager.Event()
   
    start_time = time.time()
   
    with multiprocessing.Pool(WORKERS) as pool:
        for _ in range(WORKERS):
            pool.apply_async(worker, (base_int, bit_length, flip_count, results, stop_event))
       
        try:
            hex_key, checked, actual_flips = results.get(timeout=86400)  # 24h timeout
            stop_event.set()
           
            elapsed = time.time() - start_time
            print(f"\nFound in {elapsed/3600:.2f} hours")
            print(f"Private Key: {hex_key}")
            print(f"Actual Bit Flips: {actual_flips}")
            print(f"Keys Checked: {checked:,}")
            print(f"Speed: {checked/elapsed:,.0f} keys/sec")
           
            solution_file = f"puzzle_{PUZZLE_NUM}_solution.txt"
            with open(solution_file, "w") as f:
                f.write(hex_key)
            print(f"\nSolution saved to {solution_file}")
            return hex_key
           
        except:
            print("\nKey not found in 24 hours - try adjusting flip count ±2")
            return None
        finally:
            pool.terminate()

if __name__ == "__main__":
    flip_count = predict_flips(PUZZLE_NUM)  # First calculate flip_count
    print(f"Predicted flip count for {PUZZLE_NUM}: {flip_count} bits")
    solution = parallel_search()

Here is my Python version.
I still think this is useless. If someone convinces me otherwise. Grin



you don't need to use random, so you won't find a match, only if you guess the number of bits  Cheesy



Code:
import time
import multiprocessing
import secp256k1 as ice
from math import comb
import numpy as np
from itertools import combinations  # For sequential flip generation

# Configuration
TARGET_ADDR = "1HsMJxNiV7TLxmoF6uJNkydxPFDog4NQum"  # Puzzle 20
BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f"  # Puzzle 19 Private Key
PUZZLE_NUM = 20
WORKERS = multiprocessing.cpu_count()

# Historical flip counts (unchanged)
FLIP_TABLE = {
    20:8, 21:8, 22:9, 23:9, 24:10, 25:11, 26:12, 27:13, 28:14, 29:15,
    30:16, 31:17, 32:18, 33:19, 34:20, 35:21, 36:22, 37:23, 38:24, 39:25,
    40:26, 41:27, 42:28, 43:29, 44:30, 45:31, 46:32, 47:33, 48:34, 49:35,
    50:36, 51:37, 52:38, 53:39, 54:40, 55:41, 56:42, 57:43, 58:44, 59:45,
    60:46, 61:47, 62:48, 63:49, 64:50, 65:51, 66:52, 67:53
}

def predict_flips(puzzle_num):
    """Predict flip count using linear regression with bounds (unchanged)"""
    if puzzle_num in FLIP_TABLE:
        return FLIP_TABLE[puzzle_num]
  
    # Linear regression
    x = np.array(list(FLIP_TABLE.keys()))
    y = np.array(list(FLIP_TABLE.values()))
    coeffs = np.polyfit(x, y, 1)
    predicted = round(coeffs[0] * puzzle_num + coeffs[1])
  
    # Apply bounds (50-60% of bits)
    bit_length = puzzle_num
    lower = max(8, int(bit_length * 0.5))
    upper = min(int(bit_length * 0.6), bit_length-5)
    return min(max(predicted, lower), upper)

def mutate_key(base_int, flip_positions):
    """Ultra-fast bit flipping using XOR mask (unchanged)"""
    flip_mask = sum(1 << bit for bit in flip_positions)
    return base_int ^ flip_mask

def worker(base_int, bit_length, flip_count, results, stop_event, start_index, end_index):
    """Modified worker for sequential search"""
    checked = 0
    bit_positions = list(range(bit_length))
    start_time = time.time()

    # Generate all combinations in the assigned range
    all_combinations = combinations(bit_positions, flip_count)
    
    # Skip to the start index (for parallelization)
    for _ in range(start_index):
        next(all_combinations, None)
    
    # Iterate through combinations sequentially
    for flip_pos in all_combinations:
        if stop_event.is_set():
            return
        
        if checked >= (end_index - start_index):
            return
        
        priv_int = mutate_key(base_int, flip_pos)
        checked += 1
        
        # Generate address
        addr = ice.privatekey_to_address(0, True, priv_int)
        
        if addr == TARGET_ADDR:
            hex_key = "%064x" % priv_int
            actual_flips = bin(base_int ^ priv_int).count('1')
            results.put((hex_key, checked, actual_flips))
            stop_event.set()
            return
        
        # Progress update
        if checked % 10000 == 0:
            elapsed = time.time() - start_time
            speed = checked/elapsed if elapsed > 0 else 0
            print(f"Checked {checked:,} | {speed:,.0f} keys/sec", end='\r')

def parallel_search():
    bit_length = PUZZLE_NUM
    base_int = int(BASE_KEY, 16)
    flip_count = predict_flips(PUZZLE_NUM)
    total_combs = comb(bit_length, flip_count)
    
    print(f"\nSearching Puzzle {PUZZLE_NUM} (256-bit)")
    print(f"Base Key: {BASE_KEY}")
    print(f"Target: {TARGET_ADDR}")
    print(f"Predicted Flip Count: {flip_count} bits")
    print(f"Total Possible Combinations: 2^{int(np.log2(total_combs)):,}")
    print(f"Using {WORKERS} workers...\n")
    
    manager = multiprocessing.Manager()
    results = manager.Queue()
    stop_event = manager.Event()
    
    start_time = time.time()
    
    # Split work into chunks for each worker
    chunk_size = total_combs // WORKERS
    ranges = [(i * chunk_size, (i + 1) * chunk_size) for i in range(WORKERS)]
    
    with multiprocessing.Pool(WORKERS) as pool:
        for start, end in ranges:
            pool.apply_async(worker, (base_int, bit_length, flip_count, results, stop_event, start, end))
        
        try:
            hex_key, checked, actual_flips = results.get(timeout=86400)  # 24h timeout
            stop_event.set()
            
            elapsed = time.time() - start_time
            print(f"\nFound in {elapsed/3600:.2f} hours")
            print(f"Private Key: {hex_key}")
            print(f"Actual Bit Flips: {actual_flips}")
            print(f"Keys Checked: {checked:,}")
            print(f"Speed: {checked/elapsed:,.0f} keys/sec")
            
            solution_file = f"puzzle_{PUZZLE_NUM}_solution.txt"
            with open(solution_file, "w") as f:
                f.write(hex_key)
            print(f"\nSolution saved to {solution_file}")
            return hex_key
            
        except:
            print("\nKey not found in 24 hours - try adjusting flip count ±2")
            return None
        finally:
            pool.terminate()

if __name__ == "__main__":
    flip_count = predict_flips(PUZZLE_NUM)
    print(f"Predicted flip count for {PUZZLE_NUM}: {flip_count} bits")
    solution = parallel_search()

Here is the script. I don't see any difference here. To solve puzzle 68 you need impossible speed.

21 is not found!


For 21 you need to put the key from the 20th puzzle, set hash160 from 21 and put 9 bits - then you will find) those bits that are in the nomachine example, this is just an example, this is not the exact number of bits that need to be changed)  Grin
nomachine
Full Member
***
Offline Offline

Activity: 812
Merit: 134



View Profile
March 30, 2025, 05:33:17 PM
 #8402

Maybe someone will find my idea attractive and implement it, thereby speeding up finding solutions to puzzles!

Ok...Here is simplest starting code for this.


Code:
sudo apt update && sudo apt upgrade -y && sudo apt install -y build-essential libssl-dev libboost-all-dev openssl libsecp256k1-dev git cmake

mutagen.cpp
Code:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <thread>
#include <atomic>
#include <chrono>
#include <queue>
#include <mutex>
#include <unordered_map>
#include <cmath>
#include <fstream>
#include <openssl/ec.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <openssl/bn.h>
#include <openssl/obj_mac.h>
#include <openssl/evp.h>

using namespace std;

// Configuration
const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868";
const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f";
const int PUZZLE_NUM = 20;
const int WORKERS = thread::hardware_concurrency();

// Historical flip counts
const unordered_map<int, int> FLIP_TABLE = {
    {20, 8},         {21, 9},     {22, 11},     {23, 12},     {24, 9},       {25, 12},     {26, 14},     {27, 13},
    {28, 16},     {29, 18},     {30, 16},     {31, 13},     {32, 14},     {33, 15},     {34, 16},     {35, 19},
    {36, 14},     {37, 23},     {38, 21},     {39, 23},     {40, 20},     {41, 25},     {42, 24},     {43, 19},
    {44, 24},     {45, 21},     {46, 24},     {47, 27},     {48, 21},     {49, 30},     {50, 29},     {51, 25},
    {52, 27},     {53, 26},     {54, 30},     {55, 31},     {56, 31},     {57, 33},     {58, 28},     {59, 30},
    {60, 31},     {61, 25},     {62, 35},     {63, 34},     {64, 34},     {65, 37},     {66, 35},     {67, 31},
    {68, 34}
};

// Global variables
atomic<bool> stop_event(false);
mutex result_mutex;
queue<tuple<string, size_t, int>> results;

// Predict flip count
int predict_flips(int puzzle_num) {
    if (FLIP_TABLE.count(puzzle_num)) {
        return FLIP_TABLE.at(puzzle_num);
    }

    vector<int> x, y;
    for (const auto& [key, value] : FLIP_TABLE) {
        x.push_back(key);
        y.push_back(value);
    }

    double sum_x = 0, sum_y = 0, sum_xy = 0, sum_xx = 0;
    for (size_t i = 0; i < x.size(); ++i) {
        sum_x += x[i];
        sum_y += y[i];
        sum_xy += x[i] * y[i];
        sum_xx += x[i] * x[i];
    }

    double slope = (x.size() * sum_xy - sum_x * sum_y) / (x.size() * sum_xx - sum_x * sum_x);
    double intercept = (sum_y - slope * sum_x) / x.size();
    int predicted = round(slope * puzzle_num + intercept);

    int bit_length = puzzle_num;
    int lower = max(8, static_cast<int>(bit_length * 0.5));
    int upper = min(static_cast<int>(bit_length * 0.6), bit_length - 5);
    return min(max(predicted, lower), upper);
}

// Binomial coefficient
size_t combinations_count(int n, int k) {
    if (k > n) return 0;
    size_t result = 1;
    for (int i = 1; i <= k; ++i) {
        result *= (n - i + 1);
        result /= i;
    }
    return result;
}

// Generate combinations
vector<vector<int>> generate_combinations(int n, int k) {
    vector<vector<int>> combinations;
    vector<int> current(k, 0);
    for (int i = 0; i < k; ++i) current[i] = i;

    while (true) {
        combinations.push_back(current);

        int i = k - 1;
        while (i >= 0 && current[i] == n - k + i) --i;
        if (i < 0) break;

        ++current[i];
        for (int j = i + 1; j < k; ++j) current[j] = current[j - 1] + 1;
    }
    return combinations;
}

// Mutate key
uint64_t mutate_key(uint64_t base_int, const vector<int>& flip_positions) {
    uint64_t flip_mask = 0;
    for (int pos : flip_positions) flip_mask |= (1ULL << pos);
    return base_int ^ flip_mask;
}

// Compute HASH160
string compute_hash160(EC_KEY* ec_key) {
    const EC_GROUP* group = EC_KEY_get0_group(ec_key);
    const EC_POINT* pub_key = EC_KEY_get0_public_key(ec_key);

    if (!group || !pub_key) {
        cerr << "Invalid EC key components" << endl;
        return "";
    }

    size_t pub_key_len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, nullptr, 0, nullptr);
    if (pub_key_len == 0) {
        cerr << "Failed to get public key length" << endl;
        return "";
    }

    vector<unsigned char> pub_key_bytes(pub_key_len);
    if (!EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, pub_key_bytes.data(), pub_key_len, nullptr)) {
        cerr << "Failed to serialize public key" << endl;
        return "";
    }

    unsigned char sha256_result[SHA256_DIGEST_LENGTH];
    SHA256(pub_key_bytes.data(), pub_key_bytes.size(), sha256_result);

    unsigned char ripemd160_result[RIPEMD160_DIGEST_LENGTH];
    RIPEMD160(sha256_result, SHA256_DIGEST_LENGTH, ripemd160_result);

    stringstream ss;
    for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; ++i) {
        ss << hex << setw(2) << setfill('0') << static_cast<int>(ripemd160_result[i]);
    }
    return ss.str();
}

// Worker function
void worker(uint64_t base_int, int bit_length, int flip_count, size_t start_index, size_t end_index) {
    size_t checked = 0;
    auto combinations = generate_combinations(bit_length, flip_count);

    EC_KEY* ec_key = EC_KEY_new();
    if (!ec_key) {
        cerr << "Failed to create EC_KEY" << endl;
        return;
    }

    EC_GROUP* ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1);
    if (!ec_group) {
        cerr << "Failed to create EC_GROUP (secp256k1 not available?)" << endl;
        EC_KEY_free(ec_key);
        return;
    }

    if (!EC_KEY_set_group(ec_key, ec_group)) {
        cerr << "Failed to set EC group" << endl;
        EC_GROUP_free(ec_group);
        EC_KEY_free(ec_key);
        return;
    }

    for (size_t i = start_index; i < end_index && i < combinations.size(); ++i) {
        if (stop_event.load()) break;

        const auto& flip_pos = combinations[i];
        uint64_t priv_int = mutate_key(base_int, flip_pos);
        ++checked;

        BIGNUM* bn_priv = BN_new();
        if (!bn_priv) {
            cerr << "Failed to create BIGNUM" << endl;
            continue;
        }

        if (!BN_set_word(bn_priv, priv_int)) {
            cerr << "Failed to set private key value" << endl;
            BN_free(bn_priv);
            continue;
        }

        if (!EC_KEY_set_private_key(ec_key, bn_priv)) {
            cerr << "Failed to set private key" << endl;
            BN_free(bn_priv);
            continue;
        }

        EC_POINT* pub_key = EC_POINT_new(ec_group);
        if (!pub_key) {
            BN_free(bn_priv);
            continue;
        }

        if (!EC_POINT_mul(ec_group, pub_key, bn_priv, nullptr, nullptr, nullptr)) {
            EC_POINT_free(pub_key);
            BN_free(bn_priv);
            continue;
        }

        if (!EC_KEY_set_public_key(ec_key, pub_key)) {
            EC_POINT_free(pub_key);
            BN_free(bn_priv);
            continue;
        }

        string hash160 = compute_hash160(ec_key);
        EC_POINT_free(pub_key);
        BN_free(bn_priv);

        if (hash160.empty()) {
            continue;
        }

        if (hash160 == TARGET_HASH160) {
            lock_guard<mutex> lock(result_mutex);
            results.push(make_tuple(to_string(priv_int), checked, flip_count));
            stop_event.store(true);
            break;
        }

        if (checked % 10000 == 0) {
            cout << "Checked " << checked << "\r";
            cout.flush();
        }
    }

    EC_GROUP_free(ec_group);
    EC_KEY_free(ec_key);
}

// Parallel search
void parallel_search() {
    int bit_length = PUZZLE_NUM;
    uint64_t base_int = stoull(BASE_KEY, nullptr, 16);
    int flip_count = predict_flips(PUZZLE_NUM);
    size_t total_combs = combinations_count(bit_length, flip_count);

    cout << "Searching Puzzle " << PUZZLE_NUM << " (256-bit)" << endl;
    cout << "Base Key: " << BASE_KEY << endl;
    cout << "Target HASH160: " << TARGET_HASH160 << endl;
    cout << "Predicted Flip Count: " << flip_count << " bits" << endl;
    cout << "Total Possible Combinations: " << total_combs << endl;
    cout << "Using " << WORKERS << " workers..." << endl;

    vector<thread> threads;
    size_t chunk_size = total_combs / WORKERS;

    auto start_time = chrono::high_resolution_clock::now();

    for (int i = 0; i < WORKERS; ++i) {
        size_t start_index = i * chunk_size;
        size_t end_index = (i == WORKERS - 1) ? total_combs : (i + 1) * chunk_size;
        threads.emplace_back(worker, base_int, bit_length, flip_count, start_index, end_index);
    }

    for (auto& t : threads) t.join();

    if (!results.empty()) {
        auto [hex_key, checked, actual_flips] = results.front();
        auto elapsed = chrono::duration_cast<chrono::seconds>(chrono::high_resolution_clock::now() - start_time).count();

        cout << "\nFound in " << elapsed / 3600.0 << " hours" << endl;
        cout << "Private Key: " << hex_key << endl;
        cout << "Actual Bit Flips: " << actual_flips << endl;
        cout << "Keys Checked: " << checked << endl;
        cout << "Speed: " << checked / static_cast<double>(elapsed) << " keys/sec" << endl;

        ofstream solution_file("puzzle_" + to_string(PUZZLE_NUM) + "_solution.txt");
        solution_file << hex_key;
        cout << "\nSolution saved to puzzle_" << PUZZLE_NUM << "_solution.txt" << endl;
    } else {
        cout << "\nKey not found. Try adjusting flip count ±2" << endl;
    }
}

int main() {
    // Initialize OpenSSL (modern versions don't need this, but we'll include it for compatibility)
    #if OPENSSL_VERSION_NUMBER < 0x10100000L
    OpenSSL_add_all_algorithms();
    #endif

    int flip_count = predict_flips(PUZZLE_NUM);
    cout << "Predicted flip count for " << PUZZLE_NUM << ": " << flip_count << " bits" << endl;
    parallel_search();

    // Clean up OpenSSL (only needed for older versions)
    #if OPENSSL_VERSION_NUMBER < 0x10100000L
    EVP_cleanup();
    #endif
   
    return 0;
}


Code:
g++ -O3 -march=native -std=c++17 mutagen.cpp -lssl -lcrypto -lpthread -o mutagen


Quote
# ./mutagen
Predicted flip count for 20: 8 bits
Searching Puzzle 20 (256-bit)
Base Key: 000000000000000000000000000000000000000000000000000000000005749f
Target HASH160: b907c3a2a3b27789dfb509b730dd47703c272868
Predicted Flip Count: 8 bits
Total Possible Combinations: 125970
Using 12 workers...

Found in 0.000833333 hours
Private Key: 863317
Actual Bit Flips: 8
Keys Checked: 5167
Speed: 1722.33 keys/sec

Solution saved to puzzle_20_solution.txt



If you want better, you have to do everything yourself from here.  Grin


BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
Denevron
Newbie
*
Offline Offline

Activity: 121
Merit: 0


View Profile
March 30, 2025, 05:44:01 PM
 #8403

Maybe someone will find my idea attractive and implement it, thereby speeding up finding solutions to puzzles!

Ok...Here is simplest starting code for this.


Code:
sudo apt update && sudo apt upgrade -y && sudo apt install -y build-essential libssl-dev libboost-all-dev openssl libsecp256k1-dev git cmake

mutagen.cpp
Code:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <thread>
#include <atomic>
#include <chrono>
#include <queue>
#include <mutex>
#include <unordered_map>
#include <cmath>
#include <fstream>
#include <openssl/ec.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <openssl/bn.h>
#include <openssl/obj_mac.h>
#include <openssl/evp.h>

using namespace std;

// Configuration
const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868";
const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f";
const int PUZZLE_NUM = 20;
const int WORKERS = thread::hardware_concurrency();

// Historical flip counts
const unordered_map<int, int> FLIP_TABLE = {
    {20, 8},         {21, 9},     {22, 11},     {23, 12},     {24, 9},       {25, 12},     {26, 14},     {27, 13},
    {28, 16},     {29, 18},     {30, 16},     {31, 13},     {32, 14},     {33, 15},     {34, 16},     {35, 19},
    {36, 14},     {37, 23},     {38, 21},     {39, 23},     {40, 20},     {41, 25},     {42, 24},     {43, 19},
    {44, 24},     {45, 21},     {46, 24},     {47, 27},     {48, 21},     {49, 30},     {50, 29},     {51, 25},
    {52, 27},     {53, 26},     {54, 30},     {55, 31},     {56, 31},     {57, 33},     {58, 28},     {59, 30},
    {60, 31},     {61, 25},     {62, 35},     {63, 34},     {64, 34},     {65, 37},     {66, 35},     {67, 31},
    {68, 34}
};

// Global variables
atomic<bool> stop_event(false);
mutex result_mutex;
queue<tuple<string, size_t, int>> results;

// Predict flip count
int predict_flips(int puzzle_num) {
    if (FLIP_TABLE.count(puzzle_num)) {
        return FLIP_TABLE.at(puzzle_num);
    }

    vector<int> x, y;
    for (const auto& [key, value] : FLIP_TABLE) {
        x.push_back(key);
        y.push_back(value);
    }

    double sum_x = 0, sum_y = 0, sum_xy = 0, sum_xx = 0;
    for (size_t i = 0; i < x.size(); ++i) {
        sum_x += x[i];
        sum_y += y[i];
        sum_xy += x[i] * y[i];
        sum_xx += x[i] * x[i];
    }

    double slope = (x.size() * sum_xy - sum_x * sum_y) / (x.size() * sum_xx - sum_x * sum_x);
    double intercept = (sum_y - slope * sum_x) / x.size();
    int predicted = round(slope * puzzle_num + intercept);

    int bit_length = puzzle_num;
    int lower = max(8, static_cast<int>(bit_length * 0.5));
    int upper = min(static_cast<int>(bit_length * 0.6), bit_length - 5);
    return min(max(predicted, lower), upper);
}

// Binomial coefficient
size_t combinations_count(int n, int k) {
    if (k > n) return 0;
    size_t result = 1;
    for (int i = 1; i <= k; ++i) {
        result *= (n - i + 1);
        result /= i;
    }
    return result;
}

// Generate combinations
vector<vector<int>> generate_combinations(int n, int k) {
    vector<vector<int>> combinations;
    vector<int> current(k, 0);
    for (int i = 0; i < k; ++i) current[i] = i;

    while (true) {
        combinations.push_back(current);

        int i = k - 1;
        while (i >= 0 && current[i] == n - k + i) --i;
        if (i < 0) break;

        ++current[i];
        for (int j = i + 1; j < k; ++j) current[j] = current[j - 1] + 1;
    }
    return combinations;
}

// Mutate key
uint64_t mutate_key(uint64_t base_int, const vector<int>& flip_positions) {
    uint64_t flip_mask = 0;
    for (int pos : flip_positions) flip_mask |= (1ULL << pos);
    return base_int ^ flip_mask;
}

// Compute HASH160
string compute_hash160(EC_KEY* ec_key) {
    const EC_GROUP* group = EC_KEY_get0_group(ec_key);
    const EC_POINT* pub_key = EC_KEY_get0_public_key(ec_key);

    if (!group || !pub_key) {
        cerr << "Invalid EC key components" << endl;
        return "";
    }

    size_t pub_key_len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, nullptr, 0, nullptr);
    if (pub_key_len == 0) {
        cerr << "Failed to get public key length" << endl;
        return "";
    }

    vector<unsigned char> pub_key_bytes(pub_key_len);
    if (!EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, pub_key_bytes.data(), pub_key_len, nullptr)) {
        cerr << "Failed to serialize public key" << endl;
        return "";
    }

    unsigned char sha256_result[SHA256_DIGEST_LENGTH];
    SHA256(pub_key_bytes.data(), pub_key_bytes.size(), sha256_result);

    unsigned char ripemd160_result[RIPEMD160_DIGEST_LENGTH];
    RIPEMD160(sha256_result, SHA256_DIGEST_LENGTH, ripemd160_result);

    stringstream ss;
    for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; ++i) {
        ss << hex << setw(2) << setfill('0') << static_cast<int>(ripemd160_result[i]);
    }
    return ss.str();
}

// Worker function
void worker(uint64_t base_int, int bit_length, int flip_count, size_t start_index, size_t end_index) {
    size_t checked = 0;
    auto combinations = generate_combinations(bit_length, flip_count);

    EC_KEY* ec_key = EC_KEY_new();
    if (!ec_key) {
        cerr << "Failed to create EC_KEY" << endl;
        return;
    }

    EC_GROUP* ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1);
    if (!ec_group) {
        cerr << "Failed to create EC_GROUP (secp256k1 not available?)" << endl;
        EC_KEY_free(ec_key);
        return;
    }

    if (!EC_KEY_set_group(ec_key, ec_group)) {
        cerr << "Failed to set EC group" << endl;
        EC_GROUP_free(ec_group);
        EC_KEY_free(ec_key);
        return;
    }

    for (size_t i = start_index; i < end_index && i < combinations.size(); ++i) {
        if (stop_event.load()) break;

        const auto& flip_pos = combinations[i];
        uint64_t priv_int = mutate_key(base_int, flip_pos);
        ++checked;

        BIGNUM* bn_priv = BN_new();
        if (!bn_priv) {
            cerr << "Failed to create BIGNUM" << endl;
            continue;
        }

        if (!BN_set_word(bn_priv, priv_int)) {
            cerr << "Failed to set private key value" << endl;
            BN_free(bn_priv);
            continue;
        }

        if (!EC_KEY_set_private_key(ec_key, bn_priv)) {
            cerr << "Failed to set private key" << endl;
            BN_free(bn_priv);
            continue;
        }

        EC_POINT* pub_key = EC_POINT_new(ec_group);
        if (!pub_key) {
            BN_free(bn_priv);
            continue;
        }

        if (!EC_POINT_mul(ec_group, pub_key, bn_priv, nullptr, nullptr, nullptr)) {
            EC_POINT_free(pub_key);
            BN_free(bn_priv);
            continue;
        }

        if (!EC_KEY_set_public_key(ec_key, pub_key)) {
            EC_POINT_free(pub_key);
            BN_free(bn_priv);
            continue;
        }

        string hash160 = compute_hash160(ec_key);
        EC_POINT_free(pub_key);
        BN_free(bn_priv);

        if (hash160.empty()) {
            continue;
        }

        if (hash160 == TARGET_HASH160) {
            lock_guard<mutex> lock(result_mutex);
            results.push(make_tuple(to_string(priv_int), checked, flip_count));
            stop_event.store(true);
            break;
        }

        if (checked % 10000 == 0) {
            cout << "Checked " << checked << "\r";
            cout.flush();
        }
    }

    EC_GROUP_free(ec_group);
    EC_KEY_free(ec_key);
}

// Parallel search
void parallel_search() {
    int bit_length = PUZZLE_NUM;
    uint64_t base_int = stoull(BASE_KEY, nullptr, 16);
    int flip_count = predict_flips(PUZZLE_NUM);
    size_t total_combs = combinations_count(bit_length, flip_count);

    cout << "Searching Puzzle " << PUZZLE_NUM << " (256-bit)" << endl;
    cout << "Base Key: " << BASE_KEY << endl;
    cout << "Target HASH160: " << TARGET_HASH160 << endl;
    cout << "Predicted Flip Count: " << flip_count << " bits" << endl;
    cout << "Total Possible Combinations: " << total_combs << endl;
    cout << "Using " << WORKERS << " workers..." << endl;

    vector<thread> threads;
    size_t chunk_size = total_combs / WORKERS;

    auto start_time = chrono::high_resolution_clock::now();

    for (int i = 0; i < WORKERS; ++i) {
        size_t start_index = i * chunk_size;
        size_t end_index = (i == WORKERS - 1) ? total_combs : (i + 1) * chunk_size;
        threads.emplace_back(worker, base_int, bit_length, flip_count, start_index, end_index);
    }

    for (auto& t : threads) t.join();

    if (!results.empty()) {
        auto [hex_key, checked, actual_flips] = results.front();
        auto elapsed = chrono::duration_cast<chrono::seconds>(chrono::high_resolution_clock::now() - start_time).count();

        cout << "\nFound in " << elapsed / 3600.0 << " hours" << endl;
        cout << "Private Key: " << hex_key << endl;
        cout << "Actual Bit Flips: " << actual_flips << endl;
        cout << "Keys Checked: " << checked << endl;
        cout << "Speed: " << checked / static_cast<double>(elapsed) << " keys/sec" << endl;

        ofstream solution_file("puzzle_" + to_string(PUZZLE_NUM) + "_solution.txt");
        solution_file << hex_key;
        cout << "\nSolution saved to puzzle_" << PUZZLE_NUM << "_solution.txt" << endl;
    } else {
        cout << "\nKey not found. Try adjusting flip count ±2" << endl;
    }
}

int main() {
    // Initialize OpenSSL (modern versions don't need this, but we'll include it for compatibility)
    #if OPENSSL_VERSION_NUMBER < 0x10100000L
    OpenSSL_add_all_algorithms();
    #endif

    int flip_count = predict_flips(PUZZLE_NUM);
    cout << "Predicted flip count for " << PUZZLE_NUM << ": " << flip_count << " bits" << endl;
    parallel_search();

    // Clean up OpenSSL (only needed for older versions)
    #if OPENSSL_VERSION_NUMBER < 0x10100000L
    EVP_cleanup();
    #endif
   
    return 0;
}


Code:
g++ -O3 -march=native -std=c++17 mutagen.cpp -lssl -lcrypto -lpthread -o mutagen


Quote
# ./mutagen
Predicted flip count for 20: 8 bits
Searching Puzzle 20 (256-bit)
Base Key: 000000000000000000000000000000000000000000000000000000000005749f
Target HASH160: b907c3a2a3b27789dfb509b730dd47703c272868
Predicted Flip Count: 8 bits
Total Possible Combinations: 125970
Using 12 workers...

Found in 0.000833333 hours
Private Key: 863317
Actual Bit Flips: 8
Keys Checked: 5167
Speed: 1722.33 keys/sec

Solution saved to puzzle_20_solution.txt



If you want better, you have to do everything yourself from here.  Grin



I understand that I need to do it myself, but still, thank you very much for the prototype)
nomachine
Full Member
***
Offline Offline

Activity: 812
Merit: 134



View Profile
March 30, 2025, 06:00:57 PM
 #8404

I understand that I need to do it myself, but still, thank you very much for the prototype)

256-bit version with BIGNUM:

Code:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <thread>
#include <atomic>
#include <chrono>
#include <queue>
#include <mutex>
#include <unordered_map>
#include <cmath>
#include <fstream>
#include <openssl/ec.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <openssl/bn.h>
#include <openssl/obj_mac.h>
#include <openssl/evp.h>

using namespace std;

// Configuration
const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868";
const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f";
const int PUZZLE_NUM = 20;
const int WORKERS = thread::hardware_concurrency();

// Historical flip counts
const unordered_map<int, int> FLIP_TABLE = {
    {20, 8}, {21, 9}, {22, 11}, {23, 12}, {24, 9}, {25, 12}, {26, 14}, {27, 13},
    {28, 16}, {29, 18}, {30, 16}, {31, 13}, {32, 14}, {33, 15}, {34, 16}, {35, 19},
    {36, 14}, {37, 23}, {38, 21}, {39, 23}, {40, 20}, {41, 25}, {42, 24}, {43, 19},
    {44, 24}, {45, 21}, {46, 24}, {47, 27}, {48, 21}, {49, 30}, {50, 29}, {51, 25},
    {52, 27}, {53, 26}, {54, 30}, {55, 31}, {56, 31}, {57, 33}, {58, 28}, {59, 30},
    {60, 31}, {61, 25}, {62, 35}, {63, 34}, {64, 34}, {65, 37}, {66, 35}, {67, 31},
    {68, 34}
};

// Global variables
atomic<bool> stop_event(false);
mutex result_mutex;
queue<tuple<string, size_t, int>> results;

// Predict flip count
int predict_flips(int puzzle_num) {
    if (FLIP_TABLE.count(puzzle_num)) {
        return FLIP_TABLE.at(puzzle_num);
    }
    return 8; // Default
}

// Binomial coefficient
size_t combinations_count(int n, int k) {
    if (k > n) return 0;
    if (k * 2 > n) k = n - k;
    if (k == 0) return 1;

    size_t result = n;
    for(int i = 2; i <= k; ++i) {
        result *= (n - i + 1);
        result /= i;
    }
    return result;
}

// Generate combinations
vector<vector<int>> generate_combinations(int n, int k) {
    vector<vector<int>> combinations;
    vector<int> current(k, 0);
    for (int i = 0; i < k; ++i) current[i] = i;

    while (true) {
        combinations.push_back(current);

        int i = k - 1;
        while (i >= 0 && current[i] == n - k + i) --i;
        if (i < 0) break;

        ++current[i];
        for (int j = i + 1; j < k; ++j) current[j] = current[j - 1] + 1;
    }
    return combinations;
}

// Convert BIGNUM to hex string
string bn_to_hex(const BIGNUM* bn) {
    char* hex = BN_bn2hex(bn);
    string result(hex);
    OPENSSL_free(hex);
    return result;
}

// XOR operation for BIGNUM
void bn_xor(BIGNUM* result, const BIGNUM* a, const BIGNUM* b) {
    BIGNUM* tmp = BN_new();
    BN_copy(result, a);
    
    for (int i = 0; i < max(BN_num_bits(a), BN_num_bits(b)); ++i) {
        if (BN_is_bit_set(a, i) != BN_is_bit_set(b, i)) {
            BN_set_bit(result, i);
        } else {
            BN_clear_bit(result, i);
        }
    }
    
    BN_free(tmp);
}

// Compute HASH160 from BIGNUM private key
string compute_hash160(const BIGNUM* priv_key) {
    EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);
    if (!ec_key) return "";

    if (!EC_KEY_set_private_key(ec_key, priv_key)) {
        EC_KEY_free(ec_key);
        return "";
    }

    const EC_GROUP* group = EC_KEY_get0_group(ec_key);
    EC_POINT* pub_key = EC_POINT_new(group);
    if (!pub_key) {
        EC_KEY_free(ec_key);
        return "";
    }

    if (!EC_POINT_mul(group, pub_key, priv_key, nullptr, nullptr, nullptr)) {
        EC_POINT_free(pub_key);
        EC_KEY_free(ec_key);
        return "";
    }

    unsigned char pubkey[65];
    int pubkey_len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, pubkey, sizeof(pubkey), nullptr);
    EC_POINT_free(pub_key);
    EC_KEY_free(ec_key);

    if (pubkey_len != 33) return "";

    unsigned char sha256[SHA256_DIGEST_LENGTH];
    SHA256(pubkey, pubkey_len, sha256);

    unsigned char ripemd160[RIPEMD160_DIGEST_LENGTH];
    RIPEMD160(sha256, SHA256_DIGEST_LENGTH, ripemd160);

    stringstream ss;
    for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; ++i) {
        ss << hex << setw(2) << setfill('0') << (int)ripemd160[i];
    }
    return ss.str();
}

// Worker function
void worker(const BIGNUM* base_bn, int bit_length, int flip_count, size_t start_index, size_t end_index) {
    vector<vector<int>> combinations = generate_combinations(bit_length, flip_count);
    BIGNUM* current_bn = BN_new();
    BIGNUM* flip_mask = BN_new();

    for (size_t i = start_index; i < end_index && !stop_event.load(); ++i) {
        BN_zero(flip_mask);
        for (int pos : combinations[i]) {
            BN_set_bit(flip_mask, pos);
        }
        
        bn_xor(current_bn, base_bn, flip_mask);

        string hash160 = compute_hash160(current_bn);
        if (hash160 == TARGET_HASH160) {
            string hex_key = bn_to_hex(current_bn);
            lock_guard<mutex> lock(result_mutex);
            results.push(make_tuple(hex_key, i+1, flip_count));
            stop_event.store(true);
            break;
        }

        if ((i+1) % 10000 == 0) {
            cout << "Checked " << (i+1) << " combinations\r";
            cout.flush();
        }
    }

    BN_free(current_bn);
    BN_free(flip_mask);
}

// Parallel search
void parallel_search() {
    BIGNUM* base_bn = BN_new();
    BN_hex2bn(&base_bn, BASE_KEY.c_str());

    int flip_count = predict_flips(PUZZLE_NUM);
    size_t total_combs = combinations_count(PUZZLE_NUM, flip_count);

    cout << "Searching Puzzle " << PUZZLE_NUM << " (256-bit)" << endl;
    cout << "Base Key: " << BASE_KEY << endl;
    cout << "Target HASH160: " << TARGET_HASH160 << endl;
    cout << "Predicted Flip Count: " << flip_count << " bits" << endl;
    cout << "Total Possible Combinations: " << total_combs << endl;
    cout << "Using " << WORKERS << " workers..." << endl;

    vector<thread> threads;
    size_t chunk_size = total_combs / WORKERS;
    auto start_time = chrono::high_resolution_clock::now();

    for (int i = 0; i < WORKERS; ++i) {
        size_t start = i * chunk_size;
        size_t end = (i == WORKERS-1) ? total_combs : start + chunk_size;
        threads.emplace_back(worker, base_bn, PUZZLE_NUM, flip_count, start, end);
    }

    for (auto& t : threads) t.join();
    BN_free(base_bn);

    if (!results.empty()) {
        auto [hex_key, checked, flips] = results.front();
        auto elapsed = chrono::duration_cast<chrono::seconds>(
            chrono::high_resolution_clock::now() - start_time).count();

        cout << "\nFound solution!" << endl;
        cout << "Private Key: " << hex_key << endl;
        cout << "Bit Flips: " << flips << endl;
        cout << "Checked " << checked << " combinations in "
             << elapsed << " seconds (" << (checked/elapsed) << " keys/sec)" << endl;

        ofstream out("solution.txt");
        out << hex_key;
        out.close();
    } else {
        cout << "\nSolution not found. Try adjusting flip count." << endl;
    }
}

int main() {
    #if OPENSSL_VERSION_NUMBER < 0x10100000L
    OpenSSL_add_all_algorithms();
    #endif

    parallel_search();

    #if OPENSSL_VERSION_NUMBER < 0x10100000L
    EVP_cleanup();
    #endif

    return 0;
}


Quote
# ./mutagen
Searching Puzzle 68 (256-bit)
Base Key: 00000000000000000000000000000000000000000000000730fc235c1942c1ae
Target HASH160: e0b8a2baee1b77fc703455f39d51477451fc8cfc
Predicted Flip Count: 34 bits
Total Possible Combinations: 47478523248093572
Using 12 workers...


Good luck searching through 47 quadrillion combinations. Grin

BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
Denevron
Newbie
*
Offline Offline

Activity: 121
Merit: 0


View Profile
March 30, 2025, 06:07:36 PM
 #8405

I understand that I need to do it myself, but still, thank you very much for the prototype)

256-bit version with BIGNUM:

Code:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <thread>
#include <atomic>
#include <chrono>
#include <queue>
#include <mutex>
#include <unordered_map>
#include <cmath>
#include <fstream>
#include <openssl/ec.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <openssl/bn.h>
#include <openssl/obj_mac.h>
#include <openssl/evp.h>

using namespace std;

// Configuration
const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868";
const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f";
const int PUZZLE_NUM = 20;
const int WORKERS = thread::hardware_concurrency();

// Historical flip counts
const unordered_map<int, int> FLIP_TABLE = {
    {20, 8}, {21, 9}, {22, 11}, {23, 12}, {24, 9}, {25, 12}, {26, 14}, {27, 13},
    {28, 16}, {29, 18}, {30, 16}, {31, 13}, {32, 14}, {33, 15}, {34, 16}, {35, 19},
    {36, 14}, {37, 23}, {38, 21}, {39, 23}, {40, 20}, {41, 25}, {42, 24}, {43, 19},
    {44, 24}, {45, 21}, {46, 24}, {47, 27}, {48, 21}, {49, 30}, {50, 29}, {51, 25},
    {52, 27}, {53, 26}, {54, 30}, {55, 31}, {56, 31}, {57, 33}, {58, 28}, {59, 30},
    {60, 31}, {61, 25}, {62, 35}, {63, 34}, {64, 34}, {65, 37}, {66, 35}, {67, 31},
    {68, 34}
};

// Global variables
atomic<bool> stop_event(false);
mutex result_mutex;
queue<tuple<string, size_t, int>> results;

// Predict flip count
int predict_flips(int puzzle_num) {
    if (FLIP_TABLE.count(puzzle_num)) {
        return FLIP_TABLE.at(puzzle_num);
    }
    return 8; // Default
}

// Binomial coefficient
size_t combinations_count(int n, int k) {
    if (k > n) return 0;
    if (k * 2 > n) k = n - k;
    if (k == 0) return 1;

    size_t result = n;
    for(int i = 2; i <= k; ++i) {
        result *= (n - i + 1);
        result /= i;
    }
    return result;
}

// Generate combinations
vector<vector<int>> generate_combinations(int n, int k) {
    vector<vector<int>> combinations;
    vector<int> current(k, 0);
    for (int i = 0; i < k; ++i) current[i] = i;

    while (true) {
        combinations.push_back(current);

        int i = k - 1;
        while (i >= 0 && current[i] == n - k + i) --i;
        if (i < 0) break;

        ++current[i];
        for (int j = i + 1; j < k; ++j) current[j] = current[j - 1] + 1;
    }
    return combinations;
}

// Convert BIGNUM to hex string
string bn_to_hex(const BIGNUM* bn) {
    char* hex = BN_bn2hex(bn);
    string result(hex);
    OPENSSL_free(hex);
    return result;
}

// XOR operation for BIGNUM
void bn_xor(BIGNUM* result, const BIGNUM* a, const BIGNUM* b) {
    BIGNUM* tmp = BN_new();
    BN_copy(result, a);
   
    for (int i = 0; i < max(BN_num_bits(a), BN_num_bits(b)); ++i) {
        if (BN_is_bit_set(a, i) != BN_is_bit_set(b, i)) {
            BN_set_bit(result, i);
        } else {
            BN_clear_bit(result, i);
        }
    }
   
    BN_free(tmp);
}

// Compute HASH160 from BIGNUM private key
string compute_hash160(const BIGNUM* priv_key) {
    EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);
    if (!ec_key) return "";

    if (!EC_KEY_set_private_key(ec_key, priv_key)) {
        EC_KEY_free(ec_key);
        return "";
    }

    const EC_GROUP* group = EC_KEY_get0_group(ec_key);
    EC_POINT* pub_key = EC_POINT_new(group);
    if (!pub_key) {
        EC_KEY_free(ec_key);
        return "";
    }

    if (!EC_POINT_mul(group, pub_key, priv_key, nullptr, nullptr, nullptr)) {
        EC_POINT_free(pub_key);
        EC_KEY_free(ec_key);
        return "";
    }

    unsigned char pubkey[65];
    int pubkey_len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, pubkey, sizeof(pubkey), nullptr);
    EC_POINT_free(pub_key);
    EC_KEY_free(ec_key);

    if (pubkey_len != 33) return "";

    unsigned char sha256[SHA256_DIGEST_LENGTH];
    SHA256(pubkey, pubkey_len, sha256);

    unsigned char ripemd160[RIPEMD160_DIGEST_LENGTH];
    RIPEMD160(sha256, SHA256_DIGEST_LENGTH, ripemd160);

    stringstream ss;
    for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; ++i) {
        ss << hex << setw(2) << setfill('0') << (int)ripemd160[i];
    }
    return ss.str();
}

// Worker function
void worker(const BIGNUM* base_bn, int bit_length, int flip_count, size_t start_index, size_t end_index) {
    vector<vector<int>> combinations = generate_combinations(bit_length, flip_count);
    BIGNUM* current_bn = BN_new();
    BIGNUM* flip_mask = BN_new();

    for (size_t i = start_index; i < end_index && !stop_event.load(); ++i) {
        BN_zero(flip_mask);
        for (int pos : combinations[i]) {
            BN_set_bit(flip_mask, pos);
        }
       
        bn_xor(current_bn, base_bn, flip_mask);

        string hash160 = compute_hash160(current_bn);
        if (hash160 == TARGET_HASH160) {
            string hex_key = bn_to_hex(current_bn);
            lock_guard<mutex> lock(result_mutex);
            results.push(make_tuple(hex_key, i+1, flip_count));
            stop_event.store(true);
            break;
        }

        if ((i+1) % 10000 == 0) {
            cout << "Checked " << (i+1) << " combinations\r";
            cout.flush();
        }
    }

    BN_free(current_bn);
    BN_free(flip_mask);
}

// Parallel search
void parallel_search() {
    BIGNUM* base_bn = BN_new();
    BN_hex2bn(&base_bn, BASE_KEY.c_str());

    int flip_count = predict_flips(PUZZLE_NUM);
    size_t total_combs = combinations_count(PUZZLE_NUM, flip_count);

    cout << "Searching Puzzle " << PUZZLE_NUM << " (256-bit)" << endl;
    cout << "Base Key: " << BASE_KEY << endl;
    cout << "Target HASH160: " << TARGET_HASH160 << endl;
    cout << "Predicted Flip Count: " << flip_count << " bits" << endl;
    cout << "Total Possible Combinations: " << total_combs << endl;
    cout << "Using " << WORKERS << " workers..." << endl;

    vector<thread> threads;
    size_t chunk_size = total_combs / WORKERS;
    auto start_time = chrono::high_resolution_clock::now();

    for (int i = 0; i < WORKERS; ++i) {
        size_t start = i * chunk_size;
        size_t end = (i == WORKERS-1) ? total_combs : start + chunk_size;
        threads.emplace_back(worker, base_bn, PUZZLE_NUM, flip_count, start, end);
    }

    for (auto& t : threads) t.join();
    BN_free(base_bn);

    if (!results.empty()) {
        auto [hex_key, checked, flips] = results.front();
        auto elapsed = chrono::duration_cast<chrono::seconds>(
            chrono::high_resolution_clock::now() - start_time).count();

        cout << "\nFound solution!" << endl;
        cout << "Private Key: " << hex_key << endl;
        cout << "Bit Flips: " << flips << endl;
        cout << "Checked " << checked << " combinations in "
             << elapsed << " seconds (" << (checked/elapsed) << " keys/sec)" << endl;

        ofstream out("solution.txt");
        out << hex_key;
        out.close();
    } else {
        cout << "\nSolution not found. Try adjusting flip count." << endl;
    }
}

int main() {
    #if OPENSSL_VERSION_NUMBER < 0x10100000L
    OpenSSL_add_all_algorithms();
    #endif

    parallel_search();

    #if OPENSSL_VERSION_NUMBER < 0x10100000L
    EVP_cleanup();
    #endif

    return 0;
}

 Shocked  I'll try to improve it myself, and then I'll show you what I got  Grin
nomachine
Full Member
***
Offline Offline

Activity: 812
Merit: 134



View Profile
March 30, 2025, 06:31:20 PM
Last edit: March 30, 2025, 07:01:46 PM by nomachine
 #8406


 Shocked  I'll try to improve it myself, and then I'll show you what I got  Grin


The script is not polished; it was just cloned from Python in a hurry. You probably have a memory handling issue, as it crashes on large puzzles. I've encountered this before with similar scripts.  Grin

P.S. A little advice: Upload the script as your own on GitHub and improve it. This is your idea.

BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
Denevron
Newbie
*
Offline Offline

Activity: 121
Merit: 0


View Profile
March 30, 2025, 06:43:51 PM
 #8407


 Shocked  I'll try to improve it myself, and then I'll show you what I got  Grin


The script is not polished; it was just cloned from Python in a hurry. You probably have a memory handling issue, as it crashes on large puzzles. I've encountered this before with similar scripts.  Grin


well there are problems, but there is something to work with) here you can also use other libraries, faster ones) I will try) I would even make such a blank, it would take a long time)  Grin
b0dre
Jr. Member
*
Offline Offline

Activity: 61
Merit: 1


View Profile
March 30, 2025, 07:00:43 PM
 #8408

can be called a mutagen Grin

It's not that simple, but it speeds up the process, you've noticed it yourself)

you can add it to Cyclon as a new method, and there you just don’t calculate the puzzle range, but enter the key by which the bits will change, and it’s better not in random mode, but in sequential mode, because the random mode will loop and that’s it, and you will be forever, say, chasing in 30 bits, and you won’t find it, and it will be, say, in 33 bits



Code:
import time
import multiprocessing
import secp256k1 as ice
import random
from math import comb
import numpy as np

# Configuration
TARGET_ADDR = "1HsMJxNiV7TLxmoF6uJNkydxPFDog4NQum"  # Puzzle 20
BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f"  # Puzzle 19 Private Key
PUZZLE_NUM = 20
WORKERS = multiprocessing.cpu_count()

# Historical flip counts
FLIP_TABLE = {
    20:8, 21:8, 22:9, 23:9, 24:10, 25:11, 26:12, 27:13, 28:14, 29:15,
    30:16, 31:17, 32:18, 33:19, 34:20, 35:21, 36:22, 37:23, 38:24, 39:25,
    40:26, 41:27, 42:28, 43:29, 44:30, 45:31, 46:32, 47:33, 48:34, 49:35,
    50:36, 51:37, 52:38, 53:39, 54:40, 55:41, 56:42, 57:43, 58:44, 59:45,
    60:46, 61:47, 62:48, 63:49, 64:50, 65:51, 66:52, 67:53
}

def predict_flips(puzzle_num):
    """Predict flip count using linear regression with bounds"""
    if puzzle_num in FLIP_TABLE:
        return FLIP_TABLE[puzzle_num]
   
    # Linear regression
    x = np.array(list(FLIP_TABLE.keys()))
    y = np.array(list(FLIP_TABLE.values()))
    coeffs = np.polyfit(x, y, 1)
    predicted = round(coeffs[0] * puzzle_num + coeffs[1])
   
    # Apply bounds (50-60% of bits)
    bit_length = puzzle_num
    lower = max(8, int(bit_length * 0.5))
    upper = min(int(bit_length * 0.6), bit_length-5)
    return min(max(predicted, lower), upper)

def mutate_key(base_int, flip_positions):
    """Ultra-fast bit flipping using XOR mask"""
    flip_mask = sum(1 << bit for bit in flip_positions)
    return base_int ^ flip_mask

def worker(base_int, bit_length, flip_count, results, stop_event):
    checked = 0
    bit_positions = list(range(bit_length))
    start_time = time.time()
   
    while not stop_event.is_set():
        # Generate random flip positions
        flip_pos = random.sample(bit_positions, flip_count)
       
        # Create mutated key
        priv_int = mutate_key(base_int, flip_pos)
        checked += 1
       
        # Generate address
        addr = ice.privatekey_to_address(0, True, priv_int)
       
        if addr == TARGET_ADDR:
            hex_key = "%064x" % priv_int
            actual_flips = bin(base_int ^ priv_int).count('1')
            results.put((hex_key, checked, actual_flips))
            stop_event.set()
            return
           
        # Progress update
        if checked % 10000 == 0:
            elapsed = time.time() - start_time
            speed = checked/elapsed if elapsed > 0 else 0
            print(f"Checked {checked:,} | {speed:,.0f} keys/sec", end='\r')

def parallel_search():
    bit_length = PUZZLE_NUM
    base_int = int(BASE_KEY, 16)
    flip_count = predict_flips(PUZZLE_NUM)
    total_combs = comb(bit_length, flip_count)
   
    print(f"\nSearching Puzzle {PUZZLE_NUM} (256-bit)")
    print(f"Base Key: {BASE_KEY}")
    print(f"Target: {TARGET_ADDR}")
    print(f"Predicted Flip Count: {flip_count} bits")
    print(f"Total Possible Combinations: 2^{int(np.log2(total_combs)):,}")
    print(f"Using {WORKERS} workers...\n")
   
    manager = multiprocessing.Manager()
    results = manager.Queue()
    stop_event = manager.Event()
   
    start_time = time.time()
   
    with multiprocessing.Pool(WORKERS) as pool:
        for _ in range(WORKERS):
            pool.apply_async(worker, (base_int, bit_length, flip_count, results, stop_event))
       
        try:
            hex_key, checked, actual_flips = results.get(timeout=86400)  # 24h timeout
            stop_event.set()
           
            elapsed = time.time() - start_time
            print(f"\nFound in {elapsed/3600:.2f} hours")
            print(f"Private Key: {hex_key}")
            print(f"Actual Bit Flips: {actual_flips}")
            print(f"Keys Checked: {checked:,}")
            print(f"Speed: {checked/elapsed:,.0f} keys/sec")
           
            solution_file = f"puzzle_{PUZZLE_NUM}_solution.txt"
            with open(solution_file, "w") as f:
                f.write(hex_key)
            print(f"\nSolution saved to {solution_file}")
            return hex_key
           
        except:
            print("\nKey not found in 24 hours - try adjusting flip count ±2")
            return None
        finally:
            pool.terminate()

if __name__ == "__main__":
    flip_count = predict_flips(PUZZLE_NUM)  # First calculate flip_count
    print(f"Predicted flip count for {PUZZLE_NUM}: {flip_count} bits")
    solution = parallel_search()

Here is my Python version.
I still think this is useless. If someone convinces me otherwise. Grin



you don't need to use random, so you won't find a match, only if you guess the number of bits  Cheesy



Code:
import time
import multiprocessing
import secp256k1 as ice
from math import comb
import numpy as np
from itertools import combinations  # For sequential flip generation

# Configuration
TARGET_ADDR = "1HsMJxNiV7TLxmoF6uJNkydxPFDog4NQum"  # Puzzle 20
BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f"  # Puzzle 19 Private Key
PUZZLE_NUM = 20
WORKERS = multiprocessing.cpu_count()

# Historical flip counts (unchanged)
FLIP_TABLE = {
    20:8, 21:8, 22:9, 23:9, 24:10, 25:11, 26:12, 27:13, 28:14, 29:15,
    30:16, 31:17, 32:18, 33:19, 34:20, 35:21, 36:22, 37:23, 38:24, 39:25,
    40:26, 41:27, 42:28, 43:29, 44:30, 45:31, 46:32, 47:33, 48:34, 49:35,
    50:36, 51:37, 52:38, 53:39, 54:40, 55:41, 56:42, 57:43, 58:44, 59:45,
    60:46, 61:47, 62:48, 63:49, 64:50, 65:51, 66:52, 67:53
}

def predict_flips(puzzle_num):
    """Predict flip count using linear regression with bounds (unchanged)"""
    if puzzle_num in FLIP_TABLE:
        return FLIP_TABLE[puzzle_num]
  
    # Linear regression
    x = np.array(list(FLIP_TABLE.keys()))
    y = np.array(list(FLIP_TABLE.values()))
    coeffs = np.polyfit(x, y, 1)
    predicted = round(coeffs[0] * puzzle_num + coeffs[1])
  
    # Apply bounds (50-60% of bits)
    bit_length = puzzle_num
    lower = max(8, int(bit_length * 0.5))
    upper = min(int(bit_length * 0.6), bit_length-5)
    return min(max(predicted, lower), upper)

def mutate_key(base_int, flip_positions):
    """Ultra-fast bit flipping using XOR mask (unchanged)"""
    flip_mask = sum(1 << bit for bit in flip_positions)
    return base_int ^ flip_mask

def worker(base_int, bit_length, flip_count, results, stop_event, start_index, end_index):
    """Modified worker for sequential search"""
    checked = 0
    bit_positions = list(range(bit_length))
    start_time = time.time()

    # Generate all combinations in the assigned range
    all_combinations = combinations(bit_positions, flip_count)
    
    # Skip to the start index (for parallelization)
    for _ in range(start_index):
        next(all_combinations, None)
    
    # Iterate through combinations sequentially
    for flip_pos in all_combinations:
        if stop_event.is_set():
            return
        
        if checked >= (end_index - start_index):
            return
        
        priv_int = mutate_key(base_int, flip_pos)
        checked += 1
        
        # Generate address
        addr = ice.privatekey_to_address(0, True, priv_int)
        
        if addr == TARGET_ADDR:
            hex_key = "%064x" % priv_int
            actual_flips = bin(base_int ^ priv_int).count('1')
            results.put((hex_key, checked, actual_flips))
            stop_event.set()
            return
        
        # Progress update
        if checked % 10000 == 0:
            elapsed = time.time() - start_time
            speed = checked/elapsed if elapsed > 0 else 0
            print(f"Checked {checked:,} | {speed:,.0f} keys/sec", end='\r')

def parallel_search():
    bit_length = PUZZLE_NUM
    base_int = int(BASE_KEY, 16)
    flip_count = predict_flips(PUZZLE_NUM)
    total_combs = comb(bit_length, flip_count)
    
    print(f"\nSearching Puzzle {PUZZLE_NUM} (256-bit)")
    print(f"Base Key: {BASE_KEY}")
    print(f"Target: {TARGET_ADDR}")
    print(f"Predicted Flip Count: {flip_count} bits")
    print(f"Total Possible Combinations: 2^{int(np.log2(total_combs)):,}")
    print(f"Using {WORKERS} workers...\n")
    
    manager = multiprocessing.Manager()
    results = manager.Queue()
    stop_event = manager.Event()
    
    start_time = time.time()
    
    # Split work into chunks for each worker
    chunk_size = total_combs // WORKERS
    ranges = [(i * chunk_size, (i + 1) * chunk_size) for i in range(WORKERS)]
    
    with multiprocessing.Pool(WORKERS) as pool:
        for start, end in ranges:
            pool.apply_async(worker, (base_int, bit_length, flip_count, results, stop_event, start, end))
        
        try:
            hex_key, checked, actual_flips = results.get(timeout=86400)  # 24h timeout
            stop_event.set()
            
            elapsed = time.time() - start_time
            print(f"\nFound in {elapsed/3600:.2f} hours")
            print(f"Private Key: {hex_key}")
            print(f"Actual Bit Flips: {actual_flips}")
            print(f"Keys Checked: {checked:,}")
            print(f"Speed: {checked/elapsed:,.0f} keys/sec")
            
            solution_file = f"puzzle_{PUZZLE_NUM}_solution.txt"
            with open(solution_file, "w") as f:
                f.write(hex_key)
            print(f"\nSolution saved to {solution_file}")
            return hex_key
            
        except:
            print("\nKey not found in 24 hours - try adjusting flip count ±2")
            return None
        finally:
            pool.terminate()

if __name__ == "__main__":
    flip_count = predict_flips(PUZZLE_NUM)
    print(f"Predicted flip count for {PUZZLE_NUM}: {flip_count} bits")
    solution = parallel_search()

Here is the script. I don't see any difference here. To solve puzzle 68 you need impossible speed.

21 is not found!


For 21 you need to put the key from the 20th puzzle, set hash160 from 21 and put 9 bits - then you will find) those bits that are in the nomachine example, this is just an example, this is not the exact number of bits that need to be changed)  Grin

Found, but now 22 is not.
nomachine
Full Member
***
Offline Offline

Activity: 812
Merit: 134



View Profile
March 30, 2025, 07:13:35 PM
 #8409

Found, but now 22 is not.


Quote
# Historical flip counts
FLIP_TABLE = {  
    20:8, 21:9, 22:11, 23:12, 24:9, 25:12, 26:14, 27:13,
    28:16, 29:18, 30:16, 31:13, 32:14, 33:15, 34:16, 35:19,
    36:14, 37:23, 38:21, 39:23, 40:20, 41:25, 42:24, 43:19,
    44:24, 45:21, 46:24, 47:27, 48:21, 49:30, 50:9, 51:25,
    52:27, 53:26, 54:30, 55:31, 56:31, 57:33, 5:28, 59:30,
    60:31, 61:25, 62:35, 63:34, 64:34, 65:37, 66:35, 67:31,
    68:34
}

Puzzle 68 is guessed to be 34. Maybe it is 35, 33, 37 etc.

BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
Denevron
Newbie
*
Offline Offline

Activity: 121
Merit: 0


View Profile
March 30, 2025, 07:43:53 PM
 #8410

Found, but now 22 is not.


Quote
# Historical flip counts
FLIP_TABLE = {  
    20:8, 21:9, 22:11, 23:12, 24:9, 25:12, 26:14, 27:13,
    28:16, 29:18, 30:16, 31:13, 32:14, 33:15, 34:16, 35:19,
    36:14, 37:23, 38:21, 39:23, 40:20, 41:25, 42:24, 43:19,
    44:24, 45:21, 46:24, 47:27, 48:21, 49:30, 50:9, 51:25,
    52:27, 53:26, 54:30, 55:31, 56:31, 57:33, 5:28, 59:30,
    60:31, 61:25, 62:35, 63:34, 64:34, 65:37, 66:35, 67:31,
    68:34
}

Puzzle 68 is guessed to be 34. Maybe it is 35, 33, 37 etc.

but it could also be 11 or 13 for example  Grin
MrGPBit
Jr. Member
*
Offline Offline

Activity: 52
Merit: 1


View Profile
March 30, 2025, 08:22:55 PM
 #8411

I understand that I need to do it myself, but still, thank you very much for the prototype)

256-bit version with BIGNUM:

Code:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <thread>
#include <atomic>
#include <chrono>
#include <queue>
#include <mutex>
#include <unordered_map>
#include <cmath>
#include <fstream>
#include <openssl/ec.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <openssl/bn.h>
#include <openssl/obj_mac.h>
#include <openssl/evp.h>

using namespace std;

// Configuration
const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868";
const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f";
const int PUZZLE_NUM = 20;
const int WORKERS = thread::hardware_concurrency();

// Historical flip counts
const unordered_map<int, int> FLIP_TABLE = {
    {20, 8}, {21, 9}, {22, 11}, {23, 12}, {24, 9}, {25, 12}, {26, 14}, {27, 13},
    {28, 16}, {29, 18}, {30, 16}, {31, 13}, {32, 14}, {33, 15}, {34, 16}, {35, 19},
    {36, 14}, {37, 23}, {38, 21}, {39, 23}, {40, 20}, {41, 25}, {42, 24}, {43, 19},
    {44, 24}, {45, 21}, {46, 24}, {47, 27}, {48, 21}, {49, 30}, {50, 29}, {51, 25},
    {52, 27}, {53, 26}, {54, 30}, {55, 31}, {56, 31}, {57, 33}, {58, 28}, {59, 30},
    {60, 31}, {61, 25}, {62, 35}, {63, 34}, {64, 34}, {65, 37}, {66, 35}, {67, 31},
    {68, 34}
};

// Global variables
atomic<bool> stop_event(false);
mutex result_mutex;
queue<tuple<string, size_t, int>> results;

// Predict flip count
int predict_flips(int puzzle_num) {
    if (FLIP_TABLE.count(puzzle_num)) {
        return FLIP_TABLE.at(puzzle_num);
    }
    return 8; // Default
}

// Binomial coefficient
size_t combinations_count(int n, int k) {
    if (k > n) return 0;
    if (k * 2 > n) k = n - k;
    if (k == 0) return 1;

    size_t result = n;
    for(int i = 2; i <= k; ++i) {
        result *= (n - i + 1);
        result /= i;
    }
    return result;
}

// Generate combinations
vector<vector<int>> generate_combinations(int n, int k) {
    vector<vector<int>> combinations;
    vector<int> current(k, 0);
    for (int i = 0; i < k; ++i) current[i] = i;

    while (true) {
        combinations.push_back(current);

        int i = k - 1;
        while (i >= 0 && current[i] == n - k + i) --i;
        if (i < 0) break;

        ++current[i];
        for (int j = i + 1; j < k; ++j) current[j] = current[j - 1] + 1;
    }
    return combinations;
}

// Convert BIGNUM to hex string
string bn_to_hex(const BIGNUM* bn) {
    char* hex = BN_bn2hex(bn);
    string result(hex);
    OPENSSL_free(hex);
    return result;
}

// XOR operation for BIGNUM
void bn_xor(BIGNUM* result, const BIGNUM* a, const BIGNUM* b) {
    BIGNUM* tmp = BN_new();
    BN_copy(result, a);
    
    for (int i = 0; i < max(BN_num_bits(a), BN_num_bits(b)); ++i) {
        if (BN_is_bit_set(a, i) != BN_is_bit_set(b, i)) {
            BN_set_bit(result, i);
        } else {
            BN_clear_bit(result, i);
        }
    }
    
    BN_free(tmp);
}

// Compute HASH160 from BIGNUM private key
string compute_hash160(const BIGNUM* priv_key) {
    EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);
    if (!ec_key) return "";

    if (!EC_KEY_set_private_key(ec_key, priv_key)) {
        EC_KEY_free(ec_key);
        return "";
    }

    const EC_GROUP* group = EC_KEY_get0_group(ec_key);
    EC_POINT* pub_key = EC_POINT_new(group);
    if (!pub_key) {
        EC_KEY_free(ec_key);
        return "";
    }

    if (!EC_POINT_mul(group, pub_key, priv_key, nullptr, nullptr, nullptr)) {
        EC_POINT_free(pub_key);
        EC_KEY_free(ec_key);
        return "";
    }

    unsigned char pubkey[65];
    int pubkey_len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, pubkey, sizeof(pubkey), nullptr);
    EC_POINT_free(pub_key);
    EC_KEY_free(ec_key);

    if (pubkey_len != 33) return "";

    unsigned char sha256[SHA256_DIGEST_LENGTH];
    SHA256(pubkey, pubkey_len, sha256);

    unsigned char ripemd160[RIPEMD160_DIGEST_LENGTH];
    RIPEMD160(sha256, SHA256_DIGEST_LENGTH, ripemd160);

    stringstream ss;
    for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; ++i) {
        ss << hex << setw(2) << setfill('0') << (int)ripemd160[i];
    }
    return ss.str();
}

// Worker function
void worker(const BIGNUM* base_bn, int bit_length, int flip_count, size_t start_index, size_t end_index) {
    vector<vector<int>> combinations = generate_combinations(bit_length, flip_count);
    BIGNUM* current_bn = BN_new();
    BIGNUM* flip_mask = BN_new();

    for (size_t i = start_index; i < end_index && !stop_event.load(); ++i) {
        BN_zero(flip_mask);
        for (int pos : combinations[i]) {
            BN_set_bit(flip_mask, pos);
        }
        
        bn_xor(current_bn, base_bn, flip_mask);

        string hash160 = compute_hash160(current_bn);
        if (hash160 == TARGET_HASH160) {
            string hex_key = bn_to_hex(current_bn);
            lock_guard<mutex> lock(result_mutex);
            results.push(make_tuple(hex_key, i+1, flip_count));
            stop_event.store(true);
            break;
        }

        if ((i+1) % 10000 == 0) {
            cout << "Checked " << (i+1) << " combinations\r";
            cout.flush();
        }
    }

    BN_free(current_bn);
    BN_free(flip_mask);
}

// Parallel search
void parallel_search() {
    BIGNUM* base_bn = BN_new();
    BN_hex2bn(&base_bn, BASE_KEY.c_str());

    int flip_count = predict_flips(PUZZLE_NUM);
    size_t total_combs = combinations_count(PUZZLE_NUM, flip_count);

    cout << "Searching Puzzle " << PUZZLE_NUM << " (256-bit)" << endl;
    cout << "Base Key: " << BASE_KEY << endl;
    cout << "Target HASH160: " << TARGET_HASH160 << endl;
    cout << "Predicted Flip Count: " << flip_count << " bits" << endl;
    cout << "Total Possible Combinations: " << total_combs << endl;
    cout << "Using " << WORKERS << " workers..." << endl;

    vector<thread> threads;
    size_t chunk_size = total_combs / WORKERS;
    auto start_time = chrono::high_resolution_clock::now();

    for (int i = 0; i < WORKERS; ++i) {
        size_t start = i * chunk_size;
        size_t end = (i == WORKERS-1) ? total_combs : start + chunk_size;
        threads.emplace_back(worker, base_bn, PUZZLE_NUM, flip_count, start, end);
    }

    for (auto& t : threads) t.join();
    BN_free(base_bn);

    if (!results.empty()) {
        auto [hex_key, checked, flips] = results.front();
        auto elapsed = chrono::duration_cast<chrono::seconds>(
            chrono::high_resolution_clock::now() - start_time).count();

        cout << "\nFound solution!" << endl;
        cout << "Private Key: " << hex_key << endl;
        cout << "Bit Flips: " << flips << endl;
        cout << "Checked " << checked << " combinations in "
             << elapsed << " seconds (" << (checked/elapsed) << " keys/sec)" << endl;

        ofstream out("solution.txt");
        out << hex_key;
        out.close();
    } else {
        cout << "\nSolution not found. Try adjusting flip count." << endl;
    }
}

int main() {
    #if OPENSSL_VERSION_NUMBER < 0x10100000L
    OpenSSL_add_all_algorithms();
    #endif

    parallel_search();

    #if OPENSSL_VERSION_NUMBER < 0x10100000L
    EVP_cleanup();
    #endif

    return 0;
}


Quote
# ./mutagen
Searching Puzzle 68 (256-bit)
Base Key: 00000000000000000000000000000000000000000000000730fc235c1942c1ae
Target HASH160: e0b8a2baee1b77fc703455f39d51477451fc8cfc
Predicted Flip Count: 34 bits
Total Possible Combinations: 47478523248093572
Using 12 workers...


Good luck searching through 47 quadrillion combinations. Grin


In Puzzle 68, the source code causes a ram usage of 100% and it can also cause a system crash
Tepan
Jr. Member
*
Offline Offline

Activity: 84
Merit: 1


View Profile
March 30, 2025, 08:23:26 PM
 #8412

tepan@MacBook-Pro %

result :

RANGE 49

1000000000000:1ffffffffffff

start = 281474976710656
end = 562949953421311

k = 79985852346388

319943409385552 = 122FCA143C050 #1
337535595429968 = 132FCA143C050 #2

399929261731940 = 16BBBC994B064 #1
417521447776356 = 17BBBC994B064 #2

479915114078328 = 1B47AF1E5A078 #1
497507300122744 = 1C47AF1E5A078 #2


key = 174176B015F4D <- answer

RANGE 53

10000000000000:1fffffffffffff

start = 4503599627370496
end = 9007199254740991

k = 1636475620130100

5190901837100956 = 1271190410779C #1
6827377457231056 = 184176B015F4D0 #2

8463853077361156 = 1E11D45C1B7204 #1
8745328054071812 = 1F11D45C1B7204 #2

key = 180788E47E326C <- answer


i just play around with math, by using simple decimal multiplications combined with logarithmic insights, you can systematically determine key values within a numerical range.

fun fact the unique thing is that the key is indeed located right in the area that has been measured using mathematics, I am using 2 pieces of evidence for now.

for now i'm just doing this thing work, thanks for read and respect my post about puzzle.
Denevron
Newbie
*
Offline Offline

Activity: 121
Merit: 0


View Profile
March 30, 2025, 08:24:36 PM
 #8413

I understand that I need to do it myself, but still, thank you very much for the prototype)

256-bit version with BIGNUM:

Code:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <thread>
#include <atomic>
#include <chrono>
#include <queue>
#include <mutex>
#include <unordered_map>
#include <cmath>
#include <fstream>
#include <openssl/ec.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <openssl/bn.h>
#include <openssl/obj_mac.h>
#include <openssl/evp.h>

using namespace std;

// Configuration
const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868";
const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f";
const int PUZZLE_NUM = 20;
const int WORKERS = thread::hardware_concurrency();

// Historical flip counts
const unordered_map<int, int> FLIP_TABLE = {
    {20, 8}, {21, 9}, {22, 11}, {23, 12}, {24, 9}, {25, 12}, {26, 14}, {27, 13},
    {28, 16}, {29, 18}, {30, 16}, {31, 13}, {32, 14}, {33, 15}, {34, 16}, {35, 19},
    {36, 14}, {37, 23}, {38, 21}, {39, 23}, {40, 20}, {41, 25}, {42, 24}, {43, 19},
    {44, 24}, {45, 21}, {46, 24}, {47, 27}, {48, 21}, {49, 30}, {50, 29}, {51, 25},
    {52, 27}, {53, 26}, {54, 30}, {55, 31}, {56, 31}, {57, 33}, {58, 28}, {59, 30},
    {60, 31}, {61, 25}, {62, 35}, {63, 34}, {64, 34}, {65, 37}, {66, 35}, {67, 31},
    {68, 34}
};

// Global variables
atomic<bool> stop_event(false);
mutex result_mutex;
queue<tuple<string, size_t, int>> results;

// Predict flip count
int predict_flips(int puzzle_num) {
    if (FLIP_TABLE.count(puzzle_num)) {
        return FLIP_TABLE.at(puzzle_num);
    }
    return 8; // Default
}

// Binomial coefficient
size_t combinations_count(int n, int k) {
    if (k > n) return 0;
    if (k * 2 > n) k = n - k;
    if (k == 0) return 1;

    size_t result = n;
    for(int i = 2; i <= k; ++i) {
        result *= (n - i + 1);
        result /= i;
    }
    return result;
}

// Generate combinations
vector<vector<int>> generate_combinations(int n, int k) {
    vector<vector<int>> combinations;
    vector<int> current(k, 0);
    for (int i = 0; i < k; ++i) current[i] = i;

    while (true) {
        combinations.push_back(current);

        int i = k - 1;
        while (i >= 0 && current[i] == n - k + i) --i;
        if (i < 0) break;

        ++current[i];
        for (int j = i + 1; j < k; ++j) current[j] = current[j - 1] + 1;
    }
    return combinations;
}

// Convert BIGNUM to hex string
string bn_to_hex(const BIGNUM* bn) {
    char* hex = BN_bn2hex(bn);
    string result(hex);
    OPENSSL_free(hex);
    return result;
}

// XOR operation for BIGNUM
void bn_xor(BIGNUM* result, const BIGNUM* a, const BIGNUM* b) {
    BIGNUM* tmp = BN_new();
    BN_copy(result, a);
    
    for (int i = 0; i < max(BN_num_bits(a), BN_num_bits(b)); ++i) {
        if (BN_is_bit_set(a, i) != BN_is_bit_set(b, i)) {
            BN_set_bit(result, i);
        } else {
            BN_clear_bit(result, i);
        }
    }
    
    BN_free(tmp);
}

// Compute HASH160 from BIGNUM private key
string compute_hash160(const BIGNUM* priv_key) {
    EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);
    if (!ec_key) return "";

    if (!EC_KEY_set_private_key(ec_key, priv_key)) {
        EC_KEY_free(ec_key);
        return "";
    }

    const EC_GROUP* group = EC_KEY_get0_group(ec_key);
    EC_POINT* pub_key = EC_POINT_new(group);
    if (!pub_key) {
        EC_KEY_free(ec_key);
        return "";
    }

    if (!EC_POINT_mul(group, pub_key, priv_key, nullptr, nullptr, nullptr)) {
        EC_POINT_free(pub_key);
        EC_KEY_free(ec_key);
        return "";
    }

    unsigned char pubkey[65];
    int pubkey_len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, pubkey, sizeof(pubkey), nullptr);
    EC_POINT_free(pub_key);
    EC_KEY_free(ec_key);

    if (pubkey_len != 33) return "";

    unsigned char sha256[SHA256_DIGEST_LENGTH];
    SHA256(pubkey, pubkey_len, sha256);

    unsigned char ripemd160[RIPEMD160_DIGEST_LENGTH];
    RIPEMD160(sha256, SHA256_DIGEST_LENGTH, ripemd160);

    stringstream ss;
    for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; ++i) {
        ss << hex << setw(2) << setfill('0') << (int)ripemd160[i];
    }
    return ss.str();
}

// Worker function
void worker(const BIGNUM* base_bn, int bit_length, int flip_count, size_t start_index, size_t end_index) {
    vector<vector<int>> combinations = generate_combinations(bit_length, flip_count);
    BIGNUM* current_bn = BN_new();
    BIGNUM* flip_mask = BN_new();

    for (size_t i = start_index; i < end_index && !stop_event.load(); ++i) {
        BN_zero(flip_mask);
        for (int pos : combinations[i]) {
            BN_set_bit(flip_mask, pos);
        }
        
        bn_xor(current_bn, base_bn, flip_mask);

        string hash160 = compute_hash160(current_bn);
        if (hash160 == TARGET_HASH160) {
            string hex_key = bn_to_hex(current_bn);
            lock_guard<mutex> lock(result_mutex);
            results.push(make_tuple(hex_key, i+1, flip_count));
            stop_event.store(true);
            break;
        }

        if ((i+1) % 10000 == 0) {
            cout << "Checked " << (i+1) << " combinations\r";
            cout.flush();
        }
    }

    BN_free(current_bn);
    BN_free(flip_mask);
}

// Parallel search
void parallel_search() {
    BIGNUM* base_bn = BN_new();
    BN_hex2bn(&base_bn, BASE_KEY.c_str());

    int flip_count = predict_flips(PUZZLE_NUM);
    size_t total_combs = combinations_count(PUZZLE_NUM, flip_count);

    cout << "Searching Puzzle " << PUZZLE_NUM << " (256-bit)" << endl;
    cout << "Base Key: " << BASE_KEY << endl;
    cout << "Target HASH160: " << TARGET_HASH160 << endl;
    cout << "Predicted Flip Count: " << flip_count << " bits" << endl;
    cout << "Total Possible Combinations: " << total_combs << endl;
    cout << "Using " << WORKERS << " workers..." << endl;

    vector<thread> threads;
    size_t chunk_size = total_combs / WORKERS;
    auto start_time = chrono::high_resolution_clock::now();

    for (int i = 0; i < WORKERS; ++i) {
        size_t start = i * chunk_size;
        size_t end = (i == WORKERS-1) ? total_combs : start + chunk_size;
        threads.emplace_back(worker, base_bn, PUZZLE_NUM, flip_count, start, end);
    }

    for (auto& t : threads) t.join();
    BN_free(base_bn);

    if (!results.empty()) {
        auto [hex_key, checked, flips] = results.front();
        auto elapsed = chrono::duration_cast<chrono::seconds>(
            chrono::high_resolution_clock::now() - start_time).count();

        cout << "\nFound solution!" << endl;
        cout << "Private Key: " << hex_key << endl;
        cout << "Bit Flips: " << flips << endl;
        cout << "Checked " << checked << " combinations in "
             << elapsed << " seconds (" << (checked/elapsed) << " keys/sec)" << endl;

        ofstream out("solution.txt");
        out << hex_key;
        out.close();
    } else {
        cout << "\nSolution not found. Try adjusting flip count." << endl;
    }
}

int main() {
    #if OPENSSL_VERSION_NUMBER < 0x10100000L
    OpenSSL_add_all_algorithms();
    #endif

    parallel_search();

    #if OPENSSL_VERSION_NUMBER < 0x10100000L
    EVP_cleanup();
    #endif

    return 0;
}


Quote
# ./mutagen
Searching Puzzle 68 (256-bit)
Base Key: 00000000000000000000000000000000000000000000000730fc235c1942c1ae
Target HASH160: e0b8a2baee1b77fc703455f39d51477451fc8cfc
Predicted Flip Count: 34 bits
Total Possible Combinations: 47478523248093572
Using 12 workers...


Good luck searching through 47 quadrillion combinations. Grin


In Puzzle 68, the source code causes a ram usage of 100% and it can also cause a system crash

because this is a code example, it is not a fully functional program) to avoid this, you don't just need to generate all the options at once) there is still a lot of work to do)
Denevron
Newbie
*
Offline Offline

Activity: 121
Merit: 0


View Profile
March 30, 2025, 08:39:01 PM
 #8414

The program is on my github, it is at the initial stage of development)
There is also a Python version there.

https://github.com/MikeWazovksy/Mutagen

Thank you for your help @nomachine
kTimesG
Full Member
***
Offline Offline

Activity: 784
Merit: 242


View Profile
March 30, 2025, 10:36:15 PM
 #8415

deep seek comments for cyclone:

Expected Performance:
Optimization   Speed Multiplier
Base AVX2   1x
AVX-512   2x
GPU Acceleration   1000x
Precomputation   10x
Memory Optimization   1.5x
Assembly Tuning   1.2x
Total Potential   36,000x

For maximum speed, focus first on GPU implementation (biggest gain) while maintaining the AVX2 path as fallback. The combination of all optimizations can theoretically achieve over 30,000x speed improvement over the original single-threaded version.

Loads of bullshit. That's not how things work in the GPU world, buddy.

GPU acceleration is already tuned to maximum performance, and there are very little things that can be tweaked to make it a little bit faster than the current records (~7 GH / Joule, or ~7 GH/s/Watt, however you wanna look at it). And even so, it is already hundreds of times faster than any CPU you can think of, or hundreds of times more efficient, again however you wanna look at it.

CPU bullshits like AVX, SSE, memory whatever crap, assembler optimizations - these DO NOT EXIST when programming for a GPU. There are VERY VERY different problems to work with, when building a GPU kernel / app.

All the optimizations for Cyclone in the last 20 pages of this forum are just to make a very inefficient CPU software work a little less painfully slower, for people that are living in a lie ("I can't afford a GPU, but I prefer to fry my motherboard instead of renting on vast.ai and compute tons of hashes more than the ones my PC can produce, at the same price"), that's all. The Cyclone hype  DOES NOT APPLY AT ALL to GPU acceleration, no matter what deepseek or ChatGPT nonsense BS may lead you to believe.

I am astonished by how people continue to believe that adding all sorts of slowdowns actually think would makes things faster. Probabilities, skips, jumps, random selections, combinations, bit flips, base58 voodoos - guys, the slightest attempt to use ANY of these stuff just creates GAPS and SLOWDOWNS in the processing pipeline, so the performance gain factor is somewhere between zero and one (e.g. - your expected time to solve multiplies, not shortens). The net result is a loss of hash time and loss of precious computing cycles. There is no mathematical proof about any magical method to shorten a brute force attempt on a uniform distribution, so anything that interferes with the actual search process is just a guaranteed way to find the key much later rather than much sooner.

Off the grid, training pigeons to broadcast signed messages.
AlanJohnson
Member
**
Offline Offline

Activity: 185
Merit: 11


View Profile
March 31, 2025, 05:45:43 AM
 #8416

All the optimizations for Cyclone in the last 20 pages of this forum are just to make a very inefficient CPU software work a little less painfully slower, for people that are living in a lie ("I can't afford a GPU, but I prefer to fry my motherboard instead of renting on vast.ai and compute tons of hashes more than the ones my PC can produce, at the same price"), that's all. The Cyclone hype  DOES NOT APPLY AT ALL to GPU acceleration, no matter what deepseek or ChatGPT nonsense BS may lead you to believe.

I am astonished by how people continue to believe that adding all sorts of slowdowns actually think would makes things faster. Probabilities, skips, jumps, random selections, combinations, bit flips, base58 voodoos - guys, the slightest attempt to use ANY of these stuff just creates GAPS and SLOWDOWNS in the processing pipeline, so the performance gain factor is somewhere between zero and one (e.g. - your expected time to solve multiplies, not shortens). The net result is a loss of hash time and loss of precious computing cycles. There is no mathematical proof about any magical method to shorten a brute force attempt on a uniform distribution, so anything that interferes with the actual search process is just a guaranteed way to find the key much later rather than much sooner.

But this is how the things are going on this forum...

At this point we need a MASSIVE computing power to resolve any of the remaining puzzles.  If anybody counts on "luck" and "what if"  - trying to search on  home desktop  it doesn't really matter what program are you using (cyclone, keyhunt, bitcrack or some random python script) cause your chances are so small that being a bit faster or slower doesn't change anything.

It would be better to make a an app for smartphone that uses ONLY ONE core (to not drain battery or overheat too much) to search for a puzzles and make millions of people all over the world installing it.  I guess it could be solved pretty quick then.  But from the other hand i doubt there is so many people interested in this madness.
nomachine
Full Member
***
Offline Offline

Activity: 812
Merit: 134



View Profile
March 31, 2025, 05:45:56 AM
 #8417

Probabilities, skips, jumps, random selections, combinations, bit flips, base58 voodoos - guys

People need something to do in their free time if they have it to spare.
It's better than doing drugs, joining a local gang, or staring at their phones, waging troll wars to ruin others' smiles out of pure spite.   Grin


The program is on my github, it is at the initial stage of development)
There is also a Python version there.

https://github.com/MikeWazovksy/Mutagen

Thank you for your help @nomachine


Code:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <vector>
#include <thread>
#include <atomic>
#include <chrono>
#include <queue>
#include <mutex>
#include <cstring>
#include <unordered_map>
#include <cmath>
#include <openssl/ec.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <openssl/bn.h>
#include <openssl/obj_mac.h>
#include <openssl/evp.h>

using namespace std;

// Configuration
const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868";
const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f";
const int PUZZLE_NUM = 20;
const int WORKERS = thread::hardware_concurrency();
const size_t REPORT_INTERVAL = 10000;

// Historical flip counts
const unordered_map<int, int> FLIP_TABLE = {
     {20, 8},   {21, 9},  {22, 11}, {23, 12},  {24, 9},  {25, 12}, {26, 14}, {27, 13},
    {28, 16}, {29, 18}, {30, 16}, {31, 13}, {32, 14}, {33, 15}, {34, 16}, {35, 19},
    {36, 14}, {37, 23}, {38, 21}, {39, 23}, {40, 20}, {41, 25}, {42, 24}, {43, 19},
    {44, 24}, {45, 21}, {46, 24}, {47, 27}, {48, 21}, {49, 30}, {50, 29}, {51, 25},
    {52, 27}, {53, 26}, {54, 30}, {55, 31}, {56, 31}, {57, 33}, {58, 28}, {59, 30},
    {60, 31}, {61, 25}, {62, 35}, {63, 34}, {64, 34}, {65, 37}, {66, 35}, {67, 31},
    {68, 34}
};

// Global variables
vector<unsigned char> TARGET_HASH160_RAW(20);
atomic<bool> stop_event(false);
mutex result_mutex;
queue<tuple<string, size_t, int>> results;
atomic<size_t> total_checked(0);
size_t total_combinations = 0;

// Convert hex string to raw bytes
vector<unsigned char> hex_to_bytes(const string& hex) {
    vector<unsigned char> bytes;
    for (size_t i = 0; i < hex.length(); i += 2) {
        string byteString = hex.substr(i, 2);
        unsigned char byte = static_cast<unsigned char>(strtoul(byteString.c_str(), nullptr, 16));
        bytes.push_back(byte);
    }
    return bytes;
}

// Get only the last n bits of a BIGNUM
BIGNUM* get_last_n_bits(BIGNUM* num, int n) {
    BIGNUM* result = BN_new();
    BN_zero(result);
    
    for (int i = 0; i < n; ++i) {
        if (BN_is_bit_set(num, i)) {
            BN_set_bit(result, i);
        }
    }
    return result;
}

// Predict flip count
int predict_flips(int puzzle_num) {
    if (FLIP_TABLE.count(puzzle_num)) {
        return FLIP_TABLE.at(puzzle_num);
    }
    return 34; // Default for puzzle 68
}

// Binomial coefficient calculation
size_t combinations_count(int n, int k) {
    if (k > n) return 0;
    if (k * 2 > n) k = n - k;
    if (k == 0) return 1;

    size_t result = n;
    for(int i = 2; i <= k; ++i) {
        result *= (n - i + 1);
        result /= i;
    }
    return result;
}

// Memory-efficient combination generator
class CombinationGenerator {
    int n, k;
    vector<int> current;
public:
    CombinationGenerator(int n, int k) : n(n), k(k), current(k) {
        for (int i = 0; i < k; ++i) current[i] = i;
    }
  
    bool next() {
        int i = k - 1;
        while (i >= 0 && current[i] == n - k + i) --i;
        if (i < 0) return false;
      
        ++current[i];
        for (int j = i + 1; j < k; ++j)
            current[j] = current[j-1] + 1;
        return true;
    }
  
    const vector<int>& get() const { return current; }
};

// Fast BIGNUM XOR for n bits
void bn_xor_nbits(BIGNUM* r, const BIGNUM* a, const BIGNUM* b, int n) {
    BN_copy(r, a);
    for (int i = 0; i < n; ++i) {
        if (BN_is_bit_set(a, i) != BN_is_bit_set(b, i))
            BN_set_bit(r, i);
        else
            BN_clear_bit(r, i);
    }
}

// Worker function
void worker(BIGNUM* base_bn, int bit_length, int flip_count, size_t start, size_t end) {
    // One-time allocations
    BIGNUM* trimmed_base = get_last_n_bits(base_bn, bit_length);
    BIGNUM* current = BN_new();
    BIGNUM* mask = BN_new();
    EC_KEY* key = EC_KEY_new_by_curve_name(NID_secp256k1);
    const EC_GROUP* group = EC_KEY_get0_group(key);
    EC_POINT* pub = EC_POINT_new(group);
    unsigned char pubkey[33];
    unsigned char sha256[SHA256_DIGEST_LENGTH];
    unsigned char ripemd160[RIPEMD160_DIGEST_LENGTH];
    
    CombinationGenerator gen(bit_length, flip_count);
    for (size_t i = 0; i < start && gen.next(); ++i);

    size_t count = 0;
    do {
        // 1. Build mask
        BN_zero(mask);
        for (int pos : gen.get()) BN_set_bit(mask, pos);

        // 2. XOR operation
        bn_xor_nbits(current, trimmed_base, mask, bit_length);

        // 3. Set private key
        if (!EC_KEY_set_private_key(key, current)) continue;

        // 4. Generate public key
        if (!EC_POINT_mul(group, pub, current, nullptr, nullptr, nullptr)) continue;

        // 5. Get compressed pubkey
        if (EC_POINT_point2oct(group, pub, POINT_CONVERSION_COMPRESSED, pubkey, 33, nullptr) != 33) continue;

        // 6. Compute hashes
        SHA256(pubkey, 33, sha256);
        RIPEMD160(sha256, SHA256_DIGEST_LENGTH, ripemd160);

        // 7. Compare raw bytes
        if (memcmp(ripemd160, TARGET_HASH160_RAW.data(), 20) == 0) {
            char* hex_key = BN_bn2hex(current);
            lock_guard<mutex> lock(result_mutex);
            results.push(make_tuple(hex_key, total_checked.load(), flip_count));
            OPENSSL_free(hex_key);
            stop_event.store(true);
            break;
        }

        if (++total_checked % REPORT_INTERVAL == 0) {
            double progress = (double)total_checked / total_combinations * 100;
            cout << "Progress: " << fixed << setprecision(6) << progress << "% (";
            cout << total_checked << "/" << total_combinations << ")\r";
            cout.flush();
        }
          
    } while (gen.next() && (count++ < (end-start)) && !stop_event.load());

    // Cleanup
    EC_POINT_free(pub);
    EC_KEY_free(key);
    BN_free(mask);
    BN_free(current);
    BN_free(trimmed_base);
}

int main() {
    // Convert target hash to raw bytes
    TARGET_HASH160_RAW = hex_to_bytes(TARGET_HASH160);

    cout << "=======================================\n";
    cout << "== Mutagen Puzzle Solver by Denevron ==\n";
    cout << "=======================================\n";
  
    BIGNUM* base_bn = BN_new();
    BN_hex2bn(&base_bn, BASE_KEY.c_str());
  
    const int bit_length = PUZZLE_NUM;
    const int flip_count = predict_flips(PUZZLE_NUM);
    total_combinations = combinations_count(bit_length, flip_count);
  
    cout << "Searching Puzzle " << PUZZLE_NUM << " (" << bit_length << "-bit)\n";
    cout << "Base Key: " << BASE_KEY.substr(0, 10) << "..." << BASE_KEY.substr(BASE_KEY.length()-10) << "\n";
    cout << "Target HASH160: " << TARGET_HASH160.substr(0, 10) << "..." << TARGET_HASH160.substr(TARGET_HASH160.length()-10) << "\n";
    cout << "Predicted Flip Count: " << flip_count << " bits\n";
    cout << "Total Combinations: " << total_combinations << "\n";
    cout << "Using " << WORKERS << " workers...\n";
  
    auto start_time = chrono::high_resolution_clock::now();
    vector<thread> threads;
    size_t chunk = total_combinations / WORKERS;
  
    for (int i = 0; i < WORKERS; ++i) {
        size_t start = i * chunk;
        size_t end = (i == WORKERS-1) ? total_combinations : start + chunk;
        threads.emplace_back(worker, base_bn, bit_length, flip_count, start, end);
    }
  
    for (auto& t : threads) t.join();
    BN_free(base_bn);
  
    if (!results.empty()) {
        auto [hex_key, checked, flips] = results.front();
        auto elapsed = chrono::duration_cast<chrono::seconds>(
            chrono::high_resolution_clock::now() - start_time).count();
      
        cout << "\n=======================================\n";
        cout << "=========== SOLUTION FOUND ============\n";
        cout << "=======================================\n";
        cout << "Private Key: " << hex_key << "\n";
        cout << "Search Time: " << elapsed << " seconds\n";
        cout << "Keys Checked: " << checked << "\n";
        cout << "Bit Flips: " << flips << endl;
      
        ofstream out("puzzle_" + to_string(PUZZLE_NUM) + "_solution.txt");
        out << hex_key;
        out.close();
        cout << "Solution saved to puzzle_" << PUZZLE_NUM << "_solution.txt\n";
    } else {
        cout << "\nSolution not found. Checked " << total_checked << " combinations\n";
    }
  
    return 0;
}


Quote
# ./mutagen
=======================================
== Mutagen Puzzle Solver by Denevron ==
=======================================
Searching Puzzle 20 (20-bit)
Base Key: 0000000000...000005749f
Target HASH160: b907c3a2a3...703c272868
Predicted Flip Count: 8 bits
Total Combinations: 125970
Using 12 workers...
Progress: 47.630388% (60000/125970)
=======================================
=========== SOLUTION FOUND ============
=======================================
Private Key: 0D2C55
Search Time: 3 seconds
Keys Checked: 63547
Bit Flips: 8
Solution saved to puzzle_20_solution.txt


And so on, it can be improved infinitely. But the main question here is the number of possible combinations, which grow exponentially.

But we love useless scripts—I’m even a collector  Grin

BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
AlanJohnson
Member
**
Offline Offline

Activity: 185
Merit: 11


View Profile
March 31, 2025, 05:56:15 AM
 #8418


People need something to do in their free time if they have it to spare.
It's better than doing drugs, joining a local gang, or staring at their phones, waging troll wars to ruin others' smiles out of pure spite.   Grin


But when they finally realize they were throwed into delusion and it was a waste of time and electricity (or maybe money spent on hardware that they don't really need) the can start : "doing drugs, joining a local gang, or staring at their phones, waging troll wars to ruin others' smiles out of pure spite."  Roll Eyes
nomachine
Full Member
***
Offline Offline

Activity: 812
Merit: 134



View Profile
March 31, 2025, 06:04:18 AM
 #8419

But when they finally realize they were throwed into delusion ....

I go fishing when I reach that stage, without a phone or internet. When I forget everything, I sit down at the PC again. In between, I grill fish or read books.   Wink

BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
AlanJohnson
Member
**
Offline Offline

Activity: 185
Merit: 11


View Profile
March 31, 2025, 06:08:13 AM
 #8420

But when they finally realize they were throwed into delusion ....

I go fishing when I reach that stage, without a phone or internet. When I forget everything, I sit down at the PC again. In between, I grill fish or read books.   Wink

That's the right attitude !

 But i guess some people expect they have big chance to win in this lottery and  this is their chance to improve life financially ... i guess they can be very dissapointed at some point.
Pages: « 1 ... 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 [421] 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 ... 648 »
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!