Un-vealing Scooby Doo: Origins methodChangelog:
- revert reversion in order to beat 0day prefix method
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()
=== FINAL RESULTS ===
Wins:
Scooby_Doo: 256
Prefix: 244
Ties: 0
Total Checks:
Scooby_Doo: 25374425
Prefix: 24558252
Total Time:
Scooby_Doo: 24.387615 seconds
Prefix: 24.969044 seconds
Averages (Total Time / Wins):
Scooby_Doo : 0.095264 seconds/victory
Prefix : 0.102332 seconds/victory
Checks per Win:
Scooby_Doo : 99118.85 checks/win
Prefix : 100648.57 checks/win
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. Nothing more will be disclosed. Users that wish to compare Scooby Doo with other methods have a very simple metric for comparison: the time it takes to find the correct solution.
Everyone: The Scooby Doo methods work just as better as the prefix method does. Just check out the results for yourselves. Do not listen to trolls, use your brains.
Like I said before, you guys are kind of extreme. I think there's enough proof to show that using prefixes is pretty much always the better move when searching for hashes, or at least, that's how it looks.
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?