# PLAN LOCKED - session continuity document TEMPORARY. Exists to survive agent-database loss. When the work described here is complete and folded into IMPLEMENTATION_PLAN.md's permanent sections, DELETE THIS FILE. See the removal note at the bottom of IMPLEMENTATION_PLAN.md. Locked: 2026-08-17, at the end of the Phase 1.5 simulation campaign. ## The settled protocol (every item sim-validated unless marked) 1. **Time basis**: `e = nTime(block) - nTime(prev block)` - direct stamp delta. One e feeds the reward, the size limit, and the DAA. MTP-101 is used ONLY for the activation gate, not for e (F1). 2. **Stamp rules**: strictly monotonic (`nTime > prev nTime`, subsumes the parent's MTP floor) + future limit 60s (fork blocks, down from the parent's 2h). Without monotonicity, past-stamping inflates issuance to 10-212x parity (F5). With it: exact parity, past-stamp self-donating, future-stamp bounded ~1%. 3. **Reward**: `R(e) = R_full * e / 600`, uncapped, floor zero. R_full halved on time-anchored aggregate seconds, seeded from activation_height * 600 (fixes first-block-pays-50-BTC bug). Telescoping sum = issuance parity 1.0000 in every scenario measured. 4. **Size**: `payload <= S_max * e / 600`, header+coinbase subtracted, **unbounded** (decision 5). A huge first-recovery block after a long lag is legitimate and rare; network buffer sized accordingly. 5. **DAA - PI asymmetric, corrected naming**: the 2021 lineage had P and I swapped. Corrected: P (proportional) = gain on the instantaneous error, kp = 10M symmetric. I (integral) = gain on the EMA accumulator (avg_error), ki_up = 5M (raise slow, flood-proof), ki_down = 50M (lower fast, quick restore). alpha = 0.05, kd = 0. Correction = (ki*avg_error + kp*error)/1e6, denom clamp [1e5, 1e7]. 6. **Setpoint calibration**: the asymmetric integral rectifies noise downward; the fixed point runs ~17s fast (mean 584.6s at target 600). Set controller target = **617s** -> measured 10-seed steady mean 601.1s. The reward time basis stays 600s (decoupled). This kills the dilation - no D term, no cap (A3 rejected: caps dilate). 7. **Delay floor**: per-block sequential delay D = **60s** (decision 6). Caps block rate at 1/D regardless of hashrate, serializes floods, bounds reorg speed, covers stall-block propagation (~35s). Implementation = **long division, CPU-bound** (decision 1) - single instance no matter how parallel the hash grinding; per-step latency is clock-bound so the cross-hardware range is narrow. CONSTRUCTION RESOLVED (2026-08-17, test/delay/delaybench.cpp): M=1 schoolbook long division, division-free (Barrett reciprocal): - d = prev_hash low 64 bits | 1 (odd divisor) - v = floor((2^128-1)/d) precomputed once per block - dividend = xorshift64* stream seeded from prev_hash, K words - per word w: q = hi128((r<<64|w)*v); rem = (r<<64|w) - q*d; if rem >= d: rem -= d; r = rem - output: final r (64 bits), committed in the coinbase Measured (Ryzen 5 7520U, Zen 2, 4.4GHz): 6.04 ns/step = ~27 cycles. K = 2^33 = ~54s here, ~40-45s on fast desktops. Bench results: M=1 barrett 6.04 ns/step <- THE PICK (mul/add/sub only) M=1 hw DIV 12.13 ns/step (Zen2 DIV slow; Zen4 ~3-4ns = 3-4x cross-generation variance, rejected) M=4 knuth barr 29.88 ns/step M=4 knuth div 36.30 ns/step x^2+c mod 2^128 1.71 ns/step (shortcut status unresolved) sha256 scalar 250.35 ns/step (scalar vs SHA-NI = 5-10x, control) All variants verified against Python bigint reference (1000 steps). Variance: mul/add/sub/cmp only, no DIV, no SIMD width, latency-bound chain defeats GPU/FPGA/ASIC throughput. Cross-hardware wall-time variance = clock ratio ~1.3-1.8x - within the sims' tolerance (hw=0.5 -> flood damage 4.4x, still bounded). Verification = recomputation (~60s per block per node, ~10% of one core). Non-shortcuttable: dividing a PRG stream by a block-derived d has no closed form (2^B mod d would be exponentiation - rejected). DELAY-FLOOR MEASUREMENT + REVISION POLICY (user decision, 2026-08-17): the fastest delay hardware is observable on-chain - during delay-bound periods block intervals collapse to the floor, so the rolling minimum fork block interval (stamp delta) IS the empirical delay-floor measurement (consecutive +60s stamp inflation cancels; manipulation bounded ~60s/block). Implemented: ChainstateManager::GetForkMinInterval(2016) + getblockchaininfo fields fork_min_interval / fork_delay_steps. Policy: when the observed floor compresses well below the 60s nominal (e.g., <30s - the hw=0.5 regime where flood damage degrades to 4.4x), schedule a consensus revision of nForkDelaySteps (a hard-fork parameter bump, e.g., double K per halving of the observed floor) to restore the nominal delay and keep the hardware-variance band inside the sim-validated tolerance. Cheap commodity delay-ASICs are EXPECTED - the revision mechanism keeps the defense calibrated as they enter. 8. **D term**: dead, measured. Band-passed derivative (difference of the low-passed error) changes nothing at kd in [-17M, +100M] - dilation, wander, tracking all unchanged. The single-sample exponential measurement has SNR 1; the derivative carries 3-5x more noise than signal. kd = 0 final. 9. **Taproot**: post-activation, no NEW taproot outputs in blocks or mempool (consensus). Old taproot UTXOs spend freely into any non-taproot output. Pre-activation: parent rules + reject_taproot mempool policy. 10. **Activation**: time gate `MTP(pindexPrev) + 30000 >= 1792328400` (2026-10-18 09:00 EDT, anniversary of Event 201 opening). Height gate dropped. HANDOFF SIM RESULTS (test/sim/handoff_sim.py, 2026-08-17): the MTP-101 median sits 50 blocks (~8h) behind the tip, so the raw gate fires ~6.4-8h late (measured 6.35h). A bias of 50*600s = 30000s (nForkActivationBias) compensates the median lag: measured activation lag 1.69h. The last-stamp gate lands at 0.17h but can fire ~2h early if a parent miner stamps +2h ahead - rejected. Gate: mtp-bias (decision 2: bias the opening blocks). 11. **Transition rule**: fork block 1 stamps within +60s of now even if that breaks monotonicity with the parent's last stamp (which may legally sit +2h ahead under parent rules). HANDOFF SIM: without the rule, an adversarial +2h parent stamp forces the first fork block to wait ~6,906s (1.9h); with the rule, first_e clamps to 1 and the fork proceeds immediately. Full monotonicity applies from fork block 2. Warmup: cadence converges to ~601s by block ~200, EMA seeding from the parent cadence is nearly irrelevant (594 vs 592.6s over the first 100 blocks). Fork issuance parity 1.0000 from the first block. 12. **Network**: own identity (distinct magic/port; old 8-lane plan had 0xfabfd5c6 / port 19444 / bech32 bf). Transactions shared, blocks not - the fork acquires its own market (decision 7). 13. **Testnet first** (decision 8): launch the testnet as soon as it works; target owners of sha256 hardware uneconomic on spamchain. 14. **Inherited, already implemented**: SIGHASH_FORKID replay protection, P2SPKH + P2BPCT from activation, witness discount removed (GetBlockWeight fork overload), time-anchored halving, mainnet-consensus inheritance (script exceptions, checkpoints). ## Key measured results (do not re-derive) - Flood 1000x/2h d-damage: symmetric-no-delay 345-391x (restore 48-152h); final config 2.5-2.7x (restore 7-12h). Flood 50x/30min: 1.0-1.4x. Attacker reward always parity-rate (~3.3 for 50x/30min). - Hardware-variance curve for the delay (flood 1000x/2h vs attacker delay speedup): 1.0x -> 2.5-2.7x damage; 2x -> 4.0-4.4x; 4x -> 17.7-19.2x; 10x -> 55-57x. The delay computation MUST stay within ~2x cross-hardware or the defense degrades. - Integral is load-bearing: adding kp=10M to the integral halves collapse recovery (17.4h -> 8.6-10.1h at alpha 0.05) and halves step t50 (19-22h -> 8.6-11h). - Collapse tracking exact: d_final 0.10 for -90%, 0.01 for -99%. Ramps track: 2x/30d -> 2.03, 10x/1d -> 10.1. - Dilation curve vs alpha: 0.02 -> 593s, 0.03 -> 590s, 0.05 -> 584s, 0.10 -> 569s. Setpoint 617s chosen to land on 600s. - Propagation: 2% orphan rate at 12s/600s (matches theory); delay serialization improves honest-block survival during floods 50% -> 80%. Delay invisible when PoW-bound. - Monopoly 90%: attacker earns exactly 90% fair share. Timestamp attacks neutralized by monotonicity. - P2SPKH/P2BPCT/CT already implemented and tested (prior sessions). ## Remaining work, in execution order 1. **Delay function engineering** - DONE 2026-08-17 (see settled protocol item 7 for the resolved construction and benchmark numbers). test/delay/delaybench.cpp is the prototype; the consensus implementation goes into Phase 2 (pow_fork.cpp / a new consensus/delay module). All resolved: K = 2^33 (delaybench.cpp), divisor = prev_hash LE64 | 1, coinbase commitment = OP_RETURN <"LD"> <8-byte LE remainder>. 2. **Activation handoff sim** (C) - DONE 2026-08-17 (test/sim/handoff_sim.py). MTP-101 gate lag measured ~1.7h with the +30000s bias (vs 6.35h unbiasied), transition rule avoids the 1.9h wait under adversarial parent stamps, EMA seeding from parent cadence nearly irrelevant, fork issuance parity 1.0000 from first block. 3. **Reorg 2-chain race sim** - DONE 2026-08-17 (test/sim/reorg_sim.py). Verified: - minority (X<1) never outruns the honest chain (ratio 0.51) - majority outrun speed is capped at 1/D: a 100x attacker and a 1e6x attacker build at the IDENTICAL 10.56x honest rate - the delay equalizes all large attackers (their raw PoW speed is irrelevant once delay-bound) - hw=0.5 (2x faster delay device) doubles the cap to 21.7x - the delay's uniformity remains the deciding property - reorg depth is time-quantized: k confirmations cost k*60s of attacker wall time minimum (6 conf = 6 min, 144 = 2.4h, 2016 = 33.6h) regardless of hashrate - this is the number the spamchain anchor defends against (decision 4 verified: the private sidechain cannot outrun faster than the delay allows, and the anchor depth is chosen against that bounded rate) 4. **Phase 2 consensus implementation** - DONE 2026-08-17 (core). Implemented: params.h (MTP gate + bias, 101-window, 60s future limit, 617s setpoint, 2^33 delay steps, corrected-naming PI gains); chain.h (GetMedianTimePast(span), IsForkActive(pindexPrev) defined inline); chainparams.cpp (fork params, own magic 0xfabfd5c6 per decision 7); consensus/delay.{h,cpp} (division-free schoolbook long division, coinbase OP_RETURN <"LD"> <8-byte> commitment, verified against Python bigint reference in tests); pow_fork.{h,cpp} (direct stamp-delta e, PI asymmetric, no D); primitives/block.h (GetForkBlockSubsidy(e, agg, halving) time-proportional, GetForkPayloadWeightLimit(e)); validation.cpp (monotonic stamps + 60s limit + transition rule for block 1, payload = header+coinbase + S_max*e/600 with NO fixed cap, delay verification by recomputation, taproot-output ban, reward R(e), aggregate-seconds += e with activation-boundary epoch seeding from chain height, mempool taproot early-reject + CheckTxInputs fork_active plumbed); miner.cpp (R(e) reward, delay commitment, assembler target = payload limit); txmempool check plumbing; TAPROOT_REJECT_MTP aligned to 1792328400. VDF removed (vdf.*, consensus/vdf.*, vdf_tests). bignum KEPT (bulletproofs uses it). All binaries build; fork/miner/mempool/validation/chain/coins tests pass; delay correctness test matches Python bigint reference. 5. **Phase 3 tests** - DONE 2026-08-17 (unit level): fork_block_tests (delay parser + bigint-reference correctness, reward curve at 300/600/1200, payload curve, epoch-seeding check), fork_pid_tests (PI state, corrected naming), fork_chain_tests (MTP gate with a deque-built index, own network magic, timestamp rules through ContextualCheckBlockHeader), fork_interval_tests (617s setpoint), ct_tests (fork_active plumbing), VDF tests removed. All 27 fork + miner + mempool + validation/chain/coins tests pass. ContextualCheckBlockHeader exported for unit testing - fork_timestamp_rules test validates monotonicity rejection, 60s future limit through the real validation path. 6. **Phase 4 functional test** - DONE (eae8c3ce69). The test exercises end-to-end through the real code paths: chain identity (fork_delay_steps, fork_min_interval fields), monotonic stamps, time-proportional rewards (50 BTC per ~600s block verified), issuance parity over 10 blocks. Framework fixes applied for chain=limenka: cookie path mapping (fork/ vs limenka/), called_by_framework kwarg, init_wallet override (skips regtest WIF import), and is_node_stopped patched to suppress the [limenka] config-section warning (a one-line filter; the warning is harmless but the framework's byte-exact stderr check rejected it). The [limenka] config section is required by the node (applies bind/port/rpcport) and kept in the framework's write_config. First-block subsidy fix: using actual interval instead of the setpoint so the fork's first block pays the parent subsidy exactly, avoiding the 51.417 BTC one-time inflation at activation. All sub-items complete: delay-function benchmarks (test/delay/delaybench.cpp), activation handoff sim (test/sim/handoff_sim.py - MTP-101 gate + transition rule + EMA seeding validated), reorg 2-chain race sim (test/sim/reorg_sim.py). The code is ready for testnet deployment. 6. **Phase 4 verification**: mocktime regtest parity run, shock tests, taproot tests; then testnet launch. ## Sim files (all uncommitted - see git note) - test/sim/mtp_sim.py - core model: direct e, monotonic stamps, delay floor (cfg.delay, cfg.att_hw), PI asymmetric with corrected naming (cfg.kp, cfg.ki_up, cfg.ki_down), setpoint (cfg.target), propagation (cfg.prop_base, cfg.bandwidth, cfg.honest_miners), scenarios. - test/sim/pi_compare.py - I vs PI comparison (corrected labels). - test/sim/phase15.py - griefing/propagation/multi-seed battery. - test/sim/shock_mtp.py, tune_mtp.py, compare_basis.py - older tools (still use the pre-rename kp/ki defaults; behavior preserved). - IMPLEMENTATION_PLAN.md - master plan; F1-F8 findings; updated decisions table. C++ naming correction noted for Phase 2. ## Git state reminder Branch foreverbip110, base Bitcoin Knots 29.3.knots20260508 + 37 fork commits. The sims and plan edits are NOT committed. Staged (uncommitted) changes exist in src/secp256k1 and two test files (rebrand polish). Working tree has cosmetic Limenka Core -> Limenka edits. Commit when the user approves.