Winner selection

Stretched block hash

Hookedin turns the Bitcoin closing block hash into a fixed 32-character L/H path. The path is generated progressively by repeatedly hashing the previous SHA-256 digest and reading one bit after each stretch interval.

SeedParse the 64-character Bitcoin block hash into 32 bytes. That byte array is the initial chain state.
StretchHash the current 32-byte state with SHA-256 hashesPerBisection times before reading one decision.
DecisionRead the first digest bit. A zero bit records L and keeps the low side; a one bit records H and keeps the high side.
LengthContinue the same hash chain until exactly 32 decisions have been recorded, even if the ticket range resolved earlier.

Reference Algorithm

state_0 = bytes(blockHash)
for each of 32 decisions:
  repeat hashesPerBisection times:
    state = SHA256(state)
  append L if the first state bit is 0, otherwise append H

The SHA-256 input is always the previous 32-byte digest. It is not the hex text of that digest, and it is not mixed with the round number, ticket count, or algorithm ID.

Reference JavaScript
async function stretchedBlockHash({
  blockHash,
  hashesPerBisection
}) {
  let state = hexToBytes(blockHash.toLowerCase());
  let stretchedHash = "";

  for (let decision = 0; decision < 32; decision += 1) {
    for (let index = 0; index < hashesPerBisection; index += 1) {
      state = await sha256(state);
    }
    stretchedHash += (state[0] & 0x80) === 0 ? "L" : "H";
  }

  return {
    initialSha256: blockHash.toLowerCase(),
    finalSha256: bytesToHex(state),
    stretchedHash
  };
}

async function sha256(bytes) {
  const input = new Uint8Array(bytes);
  const digest = await crypto.subtle.digest("SHA-256", input.buffer);
  return new Uint8Array(digest);
}

function hexToBytes(hex) {
  if (!/^[0-9a-f]{64}$/.test(hex)) {
    throw new Error("blockHash must be 64 lowercase hex characters");
  }
  const bytes = new Uint8Array(hex.length / 2);
  for (let index = 0; index < bytes.length; index += 1) {
    bytes[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);
  }
  return bytes;
}

function bytesToHex(bytes) {
  return Array.from(bytes, (byte) =>
    byte.toString(16).padStart(2, "0")
  ).join("");
}

Online Calculator

Browser only
Winning ticket
Pending
Algorithm
Pending
Stretched hash
Pending
Seed block hash
Pending
Initial SHA-256
Pending
Final SHA-256
Pending
Decisions
Pending