Post
Topic
Board Bitcoin Discussion
Re: Bitcoin puzzle transaction ~32 BTC prize to who solves it
by
mcdouglasx
on 20/04/2025, 19:44:05 UTC
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.


Code:
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();