That won't change anything, my friend. Are you sure you're coding it yourself? Maybe you're a chatgpt or a fiverr fan but I'm not. ^^
You can't compete with a c-bit prefilter for your linear.
#!/usr/bin/env python3
# coding: utf-8
"""
proof.py
Hash160 linear scan vs c-bit prefilter on puzzle 21.
Uses only hash160 comparisons and no Base58 encoding.
"""
import hashlib, math
from ecdsa import SECP256k1, util
from multiprocessing import Pool, cpu_count
# --- Configuration ---
ADDRESS_TARGET = "14oFNXucftsHiUMY8uctg6N487riuyXs4h"
HASH160_TARGET = "29a78213caa9eea824acf08022ab9dfc83414f56"
RANGE_HEX = "100000:1fffff"
FILTER_BITS = 2 # c ≥ 1 ⇒ >5% reduction
THRESHOLD = 5.0 # percent
# ---------------------
G = SECP256k1.generator
ORDER = SECP256k1.order
B58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
# Base58Check decode to raw payload (1-byte version + 20-byte hash160)
def b58decode(s: str) -> bytes:
num = 0
for ch in s:
num = num*58 + B58.index(ch)
nbytes = (num.bit_length() + 7)//8
b = num.to_bytes(nbytes, 'big') if nbytes else b'\x00'
pad = len(s) - len(s.lstrip('1'))
full = b'\x00'*pad + b
payload, chk = full[:-4], full[-4:]
if hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4] != chk:
raise ValueError("Invalid Base58 checksum")
return payload
# Compute RIPEMD-160(SHA256(pubkey))
def hash160_pubkey(x: int) -> bytes:
P = x * G
prefix = b'\x02' if (P.y() & 1)==0 else b'\x03'
pub = prefix + util.number_to_string(P.x(), ORDER)
return hashlib.new('ripemd160', hashlib.sha256(pub).digest()).digest()
# Prepare target H160 bytes once
def get_target_h160() -> bytes:
if HASH160_TARGET:
return bytes.fromhex(HASH160_TARGET)
payload = b58decode(ADDRESS_TARGET)
return payload[1:]
# Simple linear scan comparing hash160 directly
def linear_scan(start: int, end: int, target_h: bytes):
ops = 0
for x in range(start, end+1):
ops += 1
if hash160_pubkey(x) == target_h:
return x, ops
return None, ops
# Worker for prefilter scan chunk
def prefilter_chunk(args):
idx, start, end, c, t1, target_h = args
for i, x in enumerate(range(start, end+1), start=1):
h2 = hash160_pubkey(x)
if (int.from_bytes(h2, 'big') >> (160-c)) != t1:
continue
if h2 == target_h:
return idx, i, x
return idx, None, None
# Parallel prefilter scan using hash160 comparisons
def parallel_prefilter(start: int, end: int, c: int, target_h: bytes, workers: int):
N = end - start + 1
chunk = math.ceil(N / workers)
t1 = int.from_bytes(target_h, 'big') >> (160 - c)
args = [(i, start + i*chunk, min(start + (i+1)*chunk - 1, end), c, t1, target_h)
for i in range(workers)]
with Pool(workers) as p:
results = p.map(prefilter_chunk, args)
for idx, ops, x in sorted(results, key=lambda r: r[0]):
if ops:
return x, ops
return None, 0
# Main entry
def main():
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--workers", type=int, default=0,
help="number of processes (default = CPU count)")
args = parser.parse_args()
workers = args.workers or cpu_count()
s_hex, e_hex = RANGE_HEX.split(':')
start, end = int(s_hex, 16), int(e_hex, 16)
N = end - start + 1
print(f"Target address: {ADDRESS_TARGET}")
print(f"Range: 0x{s_hex} .. 0x{e_hex} (N = {N})")
print(f"Filter bits: {FILTER_BITS}, Processes: {workers}\n")
target_h = get_target_h160()
# Linear scan
print("→ Linear hash160 scan…")
x_lin, ops_lin = linear_scan(start, end, target_h)
print(f" ✅ Found x = 0x{x_lin:x} in {ops_lin} H160 ops")
# Prefilter scan
print("\n→ Parallel prefilter scan…")
x_pre, ops_pre = parallel_prefilter(start, end, FILTER_BITS, target_h, workers)
print(f" ✅ Found x = 0x{x_pre:x} in {ops_pre} heavy ops")
# Statistics
pct_lin = 100.0
pct_pre = ops_pre / ops_lin * 100.0 if ops_lin else 0.0
reduction = pct_lin - pct_pre
print(f"\nPercent checks: hash160 = {pct_lin:.2f}%, prefilter = {pct_pre:.2f}%")
print(f"Reduction = {reduction:.2f}%")
print(("✅" if reduction>THRESHOLD else "⚠️") +
f" Reduction {'exceeds' if reduction>THRESHOLD else 'below'} {THRESHOLD}%")
winner = "Prefilter" if ops_pre < ops_lin else "Hash160"
print("🏆 Winner: " + winner + " scan")
if __name__ == "__main__":
main()
Range: 0x100000 .. 0x1fffff (N = 1048576)