// Copyright (c) 2026 The Limenka developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef LIMENKA_CONSENSUS_DELAY_H #define LIMENKA_CONSENSUS_DELAY_H #include #include #include #include /** * Sequential per-block delay - division-free schoolbook long division. * * The delay is a consensus requirement on every fork block: the block * must commit the result of dividing a deterministic 2^33-word stream * (xorshift64* seeded from the previous block hash) by a 64-bit odd * divisor derived from the same hash. The computation is a strict * dependency chain (each remainder depends on the previous), so it * cannot be parallelized or precomputed; it binds to the block via the * hash-derived stream and divisor. * * Construction properties (measured, test/delay/delaybench.cpp): * - per-step cost is a handful of 64-bit multiplies/adds/subtracts * (Barrett reciprocal estimate, no hardware DIV): ~27 cycles on * Zen 2, and the op mix is uniform across x86/ARM - the wall-time * variance across hardware is essentially the clock-speed ratio * - non-shortcuttable: dividing a PRG stream has no closed form * (unlike 2^B mod d, which is exponentiation-by-squaring) * - verified by recomputation - the verifier redoes the same work * (~60s per block at 2^33 steps; ~10% of one core at 600s blocks) * - latency-bound: GPUs/FPGAs/ASIC throughput cannot shorten a * dependent chain; their per-op latency is not better than a CPU's */ /** Divisor and stream seed from the previous block hash. */ uint64_t DelayDivisor(const uint256& prev_hash); /** Compute the delay remainder: `steps` chained long-division words. * Deterministic; ~27 cycles per step on reference hardware. */ uint64_t ComputeDelay(const uint256& prev_hash, uint64_t steps); /** One schoolbook long-division step (exposed for tests). */ uint64_t DelayStep(uint64_t r, uint64_t w, uint64_t d, unsigned __int128 v); // Coinbase commitment: OP_RETURN <"LD"> <8-byte LE delay output>. static constexpr uint8_t DELAY_MAGIC_BYTE0 = 0x4c; // 'L' static constexpr uint8_t DELAY_MAGIC_BYTE1 = 0x44; // 'D' static constexpr int NO_DELAY_OUTPUT = -1; /** Index of the delay commitment output in the coinbase, or * NO_DELAY_OUTPUT. Last match wins (same convention as the witness * commitment). */ int GetDelayOutputIndex(const CTransaction& coinbase); /** Extract the committed delay value, or nullopt if malformed. */ std::optional GetDelayOutputValue(const CTxOut& out); #endif // LIMENKA_CONSENSUS_DELAY_H