2026-10-05 03:56:52 +00:00
|
|
|
// Synthetic local numbering: each height issues 5e9 consecutive sats. Fees retire
|
|
|
|
|
// the unassigned input tail (not Bitcoin miner fee collection). Half-open ranges.
|
|
|
|
|
export const LOCAL_REWARD = 5e9;
|
2026-10-15 02:04:35 -07:00
|
|
|
// Orgchain: coins imported from a real chain (LocalChain.importCoin) number their sats from 2^52 up, one 5e9 block of
|
|
|
|
|
// numbers each, well clear of every local coinbase's.
|
|
|
|
|
export const IMPORT_BASE = 2 ** 52;
|
|
|
|
|
export const importRanges = (index, value) => [[IMPORT_BASE + index * LOCAL_REWARD, IMPORT_BASE + index * LOCAL_REWARD + value]];
|
2026-10-05 03:56:52 +00:00
|
|
|
export function sliceRanges(ranges, offset, length) {
|
|
|
|
|
const result = [];
|
|
|
|
|
for (const [start, end] of ranges) {
|
|
|
|
|
const size = end - start;
|
|
|
|
|
if (offset >= size) { offset -= size; continue; }
|
|
|
|
|
const take = Math.min(length, size - offset);
|
|
|
|
|
if (take) result.push([start + offset, start + offset + take]);
|
|
|
|
|
length -= take; offset = 0; if (!length) break;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
export function satAt(ranges, offset) { return sliceRanges(ranges, offset, 1)[0]?.[0]; }
|
|
|
|
|
export function offsetOf(ranges, sat) {
|
|
|
|
|
let offset = 0;
|
|
|
|
|
for (const [start, end] of ranges) { if (sat >= start && sat < end) return offset + sat - start; offset += end - start; }
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
export function outputRanges(tx, coins, height, coinbase) {
|
|
|
|
|
const ranges = coinbase ? [[(height - 1) * LOCAL_REWARD, height * LOCAL_REWARD]] : coins.flatMap(c => c.ranges);
|
|
|
|
|
let offset = 0;
|
|
|
|
|
return tx.vout.map(out => { const result = sliceRanges(ranges, offset, Number(out.value)); offset += Number(out.value); return result; });
|
|
|
|
|
}
|