That's exactly what you described. Leaving "less likely" ranges for later because you think it's less likely to be there.
The
script that you sent shows that it does not change anything, both methods are equally fast on average.
Okay, I'll return to my field again. I hope this time it makes you happy.
const { performance } = require("perf_hooks");
const crypto = require("crypto");
const TOTAL_SIZE = 100_000, RANGE_SIZE = 5_000, PREFIX_LENGTH = 3, SIMULATIONS = 200;
console.log(`
=== Configuration ===
Total numbers: ${TOTAL_SIZE.toLocaleString()}
Block size: ${RANGE_SIZE.toLocaleString()}
Prefix: ${PREFIX_LENGTH} characters (16^${PREFIX_LENGTH} combinations)
Simulations: ${SIMULATIONS}
`);
const generateH160 = (data) => crypto.createHash("ripemd160").update(data.toString()).digest("hex");
const shuffledRange = (n) => {
const arr = [...Array(n + 1).keys()];
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
};
const sequentialSearch = (size, block, targetHash, order) => {
let checks = 0;
for (const idx of order) {
for (let num = idx * block; num < (idx + 1) * block; num++) {
checks++;
if (generateH160(num) === targetHash) return { checks, found: true };
}
}
return { checks, found: false };
};
const preciseSearch = (size, block, prefix, targetHash, order) => {
const prefixHash = targetHash.slice(0, prefix);
let checks = 0, ranges = [];
for (const idx of order) {
let start = idx * block, end = start + block, foundPrefix = false;
for (let num = start; num < end; num++) {
checks++;
const hash = generateH160(num);
if (hash === targetHash) return { checks, found: true };
if (!foundPrefix && hash.startsWith(prefixHash)) {
foundPrefix = true;
ranges.push({ start: num + 1, end });
break;
}
}
}
for (const { start, end } of ranges) {
for (let num = end - 1; num >= start; num--) {
checks++;
if (generateH160(num) === targetHash) return { checks, found: true };
}
}
return { checks, found: false };
};
const compareMethods = async () => {
[...Array(5).keys()].forEach((i) => generateH160(i));
const results = { sequential: { wins: 0 }, precise: { wins: 0 }, ties: 0 };
for (let i = 0; i < SIMULATIONS; i++) {
const blocks = Math.floor(TOTAL_SIZE / RANGE_SIZE), order = shuffledRange(blocks - 1);
const targetNum = Math.floor(Math.random() * TOTAL_SIZE), targetHash = generateH160(targetNum);
const seqResult = sequentialSearch(TOTAL_SIZE, RANGE_SIZE, targetHash, order);
const preResult = preciseSearch(TOTAL_SIZE, RANGE_SIZE, PREFIX_LENGTH, targetHash, order);
if (seqResult.checks < preResult.checks) {
results.sequential.wins++;
} else if (seqResult.checks > preResult.checks) {
results.precise.wins++;
} else {
results.ties++;
}
console.log(`Simulation ${i + 1}: Sequential = ${seqResult.checks} | Precise = ${preResult.checks}`);
}
console.log(`
=== FINAL RESULTS ===
Wins:
Sequential: ${results.sequential.wins}
Precise: ${results.precise.wins}
Ties: ${results.ties}
`);
};
compareMethods();