import hashlib
import random
import time
# Configuration
TOTAL_SIZE = 100_000
RANGE_SIZE = 5_000
PREFIX_LENGTH = 3
SIMULATIONS = 500
SECP256K1_ORDER = int("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
# ENABLE REPRODUCIBLE TESTING
# Note: this line can be safely kept for a release build
random.seed(int.from_bytes(b'mcdouglasx'))
def ScoobyDoo_Origins(dataset, block, target_hash, order):
checks = 0
for k in dataset:
checks += 1
if generate_h160(k) == target_hash:
return {"checks": checks, "found": True}
raise Exception('OHNOES. Your Programming Language Is Rigged!')
def generate_h160(data):
h = hashlib.new('ripemd160', str(data).encode('utf-8'))
return h.hexdigest()
def shuffled_range(n):
arr = list(range(n + 1))
random.shuffle(arr)
return arr
def prefixes_search(dataset, block, prefix, target_hash, order):
prefix_hash = target_hash[:prefix]
checks = 0
skipped_indices = []
skip_window = 4096
skip_percentage = 0.3
i = len(dataset) - 1
while i >= 0:
checks += 1
h = generate_h160(dataset[i])
if h == target_hash:
return {"checks": checks, "found": True}
if h.startswith(prefix_hash):
skip_count = int(skip_window * skip_percentage)
for j in range(i-1, max(i-1 - skip_count, -1), -1):
skipped_indices.append(j)
i -= skip_count + 1 # +1
else:
i -= 1
for idx in sorted(skipped_indices, reverse=True):
checks += 1
if generate_h160(dataset[idx]) == target_hash:
return {"checks": checks, "found": True}
return {"checks": checks, "found": False}
def compare_methods():
results = {
"Scooby_Doo": {"wins": 0, "total_checks": 0, "total_time": 0},
"prefixes": {"wins": 0, "total_checks": 0, "total_time": 0},
"ties": 0
}
for i in range(SIMULATIONS):
max_range = SECP256K1_ORDER - TOTAL_SIZE - 1
random_offset = random.randrange(max_range)
R = 1 + random_offset
dataset = [R + i for i in range(TOTAL_SIZE)]
target_num = random.choice(dataset)
target_hash = generate_h160(target_num)
blocks = TOTAL_SIZE // RANGE_SIZE
order = shuffled_range(blocks - 1)
start_time = time.perf_counter()
seq_result = ScoobyDoo_Origins(dataset, RANGE_SIZE, target_hash, order)
end_time = time.perf_counter()
seq_time = end_time - start_time
start_time = time.perf_counter()
pre_result = prefixes_search(dataset, RANGE_SIZE, PREFIX_LENGTH, target_hash, order)
end_time = time.perf_counter()
pre_time = end_time - start_time
results["Scooby_Doo"]["total_checks"] += seq_result["checks"]
results["prefixes"]["total_checks"] += pre_result["checks"]
results["Scooby_Doo"]["total_time"] += seq_time
results["prefixes"]["total_time"] += pre_time
if seq_result["checks"] < pre_result["checks"]:
results["Scooby_Doo"]["wins"] += 1
elif seq_result["checks"] > pre_result["checks"]:
results["prefixes"]["wins"] += 1
else:
results["ties"] += 1
print(f"Simulation {i + 1}: Scooby_Doo = {seq_result['checks']} checks in {seq_time:.6f}s | Prefix = {pre_result['checks']} checks in {pre_time:.6f}s")
avg_success_rate_Scooby_Doo = (results["Scooby_Doo"]["total_checks"] / results["Scooby_Doo"]["wins"]
if results["Scooby_Doo"]["wins"] > 0 else float('inf'))
avg_success_rate_prefixes = (results["prefixes"]["total_checks"] / results["prefixes"]["wins"]
if results["prefixes"]["wins"] > 0 else float('inf'))
avg_time_Scooby_Doo = (results["Scooby_Doo"]["total_time"] / results["Scooby_Doo"]["wins"]
if results["Scooby_Doo"]["wins"] > 0 else float('inf'))
avg_time_prefixes = (results["prefixes"]["total_time"] / results["prefixes"]["wins"]
if results["prefixes"]["wins"] > 0 else float('inf'))
print(f"""
=== FINAL RESULTS ===
Wins:
Scooby_Doo: {results['Scooby_Doo']['wins']}
Prefix: {results['prefixes']['wins']}
Ties: {results['ties']}
Total Checks:
Scooby_Doo: {results['Scooby_Doo']['total_checks']}
Prefix: {results['prefixes']['total_checks']}
Total Time:
Scooby_Doo: {results['Scooby_Doo']['total_time']:.6f} seconds
Prefix: {results['prefixes']['total_time']:.6f} seconds
Averages (Total Time / Wins):
Scooby_Doo : {avg_time_Scooby_Doo:.6f} seconds/victory
Prefix : {avg_time_prefixes:.6f} seconds/victory
Checks per Win:
Scooby_Doo : {avg_success_rate_Scooby_Doo:.2f} checks/win
Prefix : {avg_success_rate_prefixes:.2f} checks/win
""")
print(f"""
=== Configuration ===
Total numbers: {TOTAL_SIZE:,}
Block size: {RANGE_SIZE:,}
Prefix: {PREFIX_LENGTH} characters (16^{PREFIX_LENGTH} combinations)
Simulations: {SIMULATIONS}
secp256k1 Order: {SECP256K1_ORDER}
""")
if __name__ == '__main__':
compare_methods()
Note: future versions of Scooby Doo reserve the right to become closed-source, in order to protect from reverse engineering.
On another note: this is a never ending story. If Scooby Doo does random picks, someone will want to know the exact order of those random picks.
If Scooby Doo does quantum entanglement, someone will want to know the exact quantum state of the entanglement.
This is not acceptable. In effect, future versions of Scooby Doo will only ever accept as input the dataset that is to be searched, and the target to be found.
.
Yes, the truth is an extreme. What do you mean by "pretty much always"? Looks more like "never". Also, where is the proof you are talking about? And lastly, how does what looks? The Scooby Doo methods clearly show it finds the key faster or at least as fast as any prefix method. Do you want a link to the Scooby Doo methods?