Post
Topic
Board Bitcoin Discussion
Re: Bitcoin puzzle transaction ~32 BTC prize to who solves it
by
nomachine
on 12/02/2025, 06:26:39 UTC
Ole, FE57, oldie but goodie!  I believe it's sprinkled in the python script as well.  But this was one of the first Python scripts that I remember seeing put out for the public. Many worked on it.

I'm wondering if going from GMP to iceland's package, would offer some speed up.

It might be 5% faster.  Grin

Code:
# based on http://fe57.org/forum/thread.php?board=4&thema=1
import time, os, sys
from secrets import randbelow
import secp256k1 #https://github.com/iceland2k14/secp256k1
from math import log2, sqrt, log

os.system("cls||clear")
t = time.ctime()
sys.stdout.write(f"\033[?25l\033[01;33m[+] Kangaroo: {t}\n")
sys.stdout.flush()

def generate_powers_of_two(hop_modulo):
    return [1 << pw for pw in range(hop_modulo)]

def handle_solution(solution):
    HEX = f"{abs(solution):064x}"
    dec = int(HEX, 16)
    print(f"\n\033[32m[+] PUZZLE SOLVED \033[0m")
    print(f"\033[32m[+] Private key (dec): {dec} \033[0m")
    with open("KEYFOUNDKEYFOUND.txt", "a") as file:
        file.write(f"\n\nSOLVED {t}\nPrivate Key (decimal): {dec}\nPrivate Key (hex): {HEX}\n{'-' * 130}\n")
    return True

def search(W0, DP_rarity, Nw, Nt, hop_modulo, end, start, powers_of_two, P_table):
    solved = False
    rand_range = end - start
    t_values = [start + randbelow(rand_range) for _ in range(Nt)]
    w_values = [randbelow(rand_range) for _ in range(Nw)]
    T = [secp256k1.scalar_multiplication(ti) for ti in t_values]
    W = [secp256k1.point_addition(W0, secp256k1.scalar_multiplication(wk)) for wk in w_values]  
    dt = [0] * Nt
    dw = [0] * Nw
    tame_points, wild_points = {}, {}  
    print('[+] Tame and wild herds prepared')
    last_print_time = starttime = time.time()
    Hops, Hops_old = 0, 0  
    while not solved:
        current_time = time.time()
        for k, Tk in enumerate(T):
            Hops += 1
            pub_t = secp256k1.point_to_cpub(Tk)[2:].zfill(64)
            pw = int(pub_t, 16) % hop_modulo
            dt[k] = powers_of_two[pw]          
            if int(pub_t, 16) & (DP_rarity - 1) == 0:  # DP check
                tame_points[pub_t] = t_values[k]
                if pub_t in wild_points:
                    return handle_solution(t_values[k] - wild_points[pub_t])        
            t_values[k] += dt[k]
            T[k] = secp256k1.point_addition(P_table[pw], Tk)
        for k, Wk in enumerate(W):
            Hops += 1
            pub_w = secp256k1.point_to_cpub(Wk)[2:].zfill(64)
            pw = int(pub_w, 16) % hop_modulo
            dw[k] = powers_of_two[pw]          
            if int(pub_w, 16) & (DP_rarity - 1) == 0:  # DP check
                wild_points[pub_w] = w_values[k]
                if pub_w in tame_points:
                    return handle_solution(tame_points[pub_w] - w_values[k])        
            w_values[k] += dw[k]
            W[k] = secp256k1.point_addition(P_table[pw], Wk)
        
        if current_time - last_print_time >= 5:
            elapsed_time = current_time - starttime
            hops_since_last = Hops - Hops_old
            hops_per_second = hops_since_last / (current_time - last_print_time)
            last_print_time = current_time
            Hops_old = Hops
            elapsed_time_str = time.strftime('%H:%M:%S', time.gmtime(elapsed_time))
            hops_log = f'{log2(Hops):.2f}' if Hops > 0 else '0.00'
            print(f'[+] [Hops: 2^{hops_log} <-> {hops_per_second:.0f} h/s] [{elapsed_time_str}]',
                  end='\r', flush=True)

    print('\r[+] Hops:', Hops)
    print(f'[+] Average time to solve: {time.time() - starttime:.2f} sec')

# Configuration
puzzle = 40
compressed_public_key = "03a2efa402fd5268400c77c20e574ba86409ededee7c4020e4b9f0edbee53de0d4"
kangaroo_power = puzzle // 5
start, end = 2**(puzzle-1), (2**puzzle) - 1
DP_rarity = 1 << ((puzzle - 1) // 2 - 2) // 2 + 2
hop_modulo = round(log(2**puzzle)+5)
Nt = Nw = 2**kangaroo_power
powers_of_two = generate_powers_of_two(hop_modulo)

P_table = []
pk = 1
for _ in range(255):
    P_table.append(secp256k1.scalar_multiplication(pk))
    pk *= 2    
print(f"[+] P-table prepared with {len(P_table)} points")

W0 = secp256k1.pub2upub(compressed_public_key)
starttime = time.time()

print(f"[+] Puzzle: {puzzle}")
print(f"[+] Lower range limit: {start}")
print(f"[+] Upper range limit: {end}")
print(f"[+] DP: 2^{int(log2(DP_rarity))} ({DP_rarity:d})")
print(f"[+] Expected Hops: 2^{log2(2 * sqrt(1 << puzzle)):.2f} ({int(2 * sqrt(1 << puzzle))})")

search(W0, DP_rarity, Nw, Nt, hop_modulo, end, start, powers_of_two, P_table)
print(f"[+] Total time: {time.time() - starttime:.2f} seconds")


  • Kangaroo: Wed Feb 12 07:18:30 2025
  • P-table prepared with 255 points
  • Puzzle: 40
  • Lower range limit: 549755813888
  • Upper range limit: 1099511627775
  • DP: 2^10 (1024)
  • Expected Hops: 2^21.00 (2097152)
  • Tame and wild herds prepared
  • [Hops: 2^20.28 <-> 253984 h/s] [00:00:05]
  • PUZZLE SOLVED
  • Private key (dec): 1003651412950
  • Total time: 6.89 seconds