|
| 1 | +# V37 MRR Roundabout Round-Buffer — implementation notes (WIP for review) |
| 2 | + |
| 3 | +Branch: `v37/mrr-roundabout-buffer`. Spec: `c2pool-v37-mrr-roundabout-buffer.md` v1.0 |
| 4 | +(all OQ/S decisions resolved). Module: `src/sharechain/v37/`, header-only, |
| 5 | +`namespace v37`, stdlib-only — compiles and tests standalone with |
| 6 | +`g++ -std=c++20`, no conan/boost/btclibs dependency. |
| 7 | + |
| 8 | +## Done (implemented + tested on this VM) |
| 9 | + |
| 10 | +| Component (brief) | Where | Status | |
| 11 | +|---|---|---| |
| 12 | +| 1. Lane storage, bucket leaves (F-1 fields) | `v37_lane.hpp` | done | |
| 13 | +| 2. MRR roll-up pyramid (OQ-5 geometry) | `v37_lane.hpp` (`fold_l0`, `cascade_folds`) | done; L=2 default fully tested, L≥3 see notes | |
| 14 | +| 3. Epoch-scaled incremental decay + OQ-2 exact rebuild | `v37_lane.hpp` (`push`, `epoch_rebuild`) | done | |
| 15 | +| 4. PayoutDescriptor v1 (OQ-3, S-1/S-2/S-3) | `v37_descriptor.hpp` | done | |
| 16 | +| 5. Quantized window (OQ-1) + reorg journal D=64 (OQ-7) | `v37_lane.hpp` (`evict_oldest_bucket`, `rewind`) | done | |
| 17 | +| 6. Lane digest (§8.5, OQ-4) | `v37_lane.hpp` (`digest`) | done | |
| 18 | +| 7. Fixed-point model + slow reference + bit-exact gate | `v37_fixed.hpp` + `test/v37_test.cpp` (`ReferenceLane`) | done | |
| 19 | +| Multichain container + miner intern | `v37_roundabout.hpp` | done | |
| 20 | + |
| 21 | +Test run (g++ 13.3, -O2 and again under `-fsanitize=address,undefined`): |
| 22 | +**100,338 checks, 0 failures.** The consensus gate is `ReferenceLane` — an |
| 23 | +independent implementation whose per-miner weights are recomputed by full |
| 24 | +scan of the durable records after EVERY push — compared bit-exact against the |
| 25 | +incremental accumulators, across two geometries (small stress geometry, 5+ |
| 26 | +epochs; ratified OQ-5 default geometry across two epoch rebuilds, ~9.5k |
| 27 | +pushes, full-u64-range weights). Also covered: digest determinism + |
| 28 | +sensitivity, rewind bit-exact restoration, window quantization, raw-work |
| 29 | +conservation (F-1), descriptor canon vectors for all five template kinds + |
| 30 | +kind-255 fallback, S-1 identity distinctness, aux/attribution validity rules, |
| 31 | +runtime lane add/remove, cross-lane identity intern. |
| 32 | + |
| 33 | +## Range pinning + spec errata (flag for the spec's next revision) |
| 34 | + |
| 35 | +1. **Q62, not Q64.** §8.2 says "widens to 64 fractional bits"; §8.1 delegates |
| 36 | + exact range pinning here. Pinned at FRAC_BITS = 62 so that: every table |
| 37 | + entry (decay ≤ 1.0, inverse ≤ 2^1.9) fits u64; w_raw keeps the FULL u64 |
| 38 | + range; every w_raw × table product fits native unsigned __int128; |
| 39 | + accumulators fit 256 bits. Still 2^22 finer than V36's Q40. Suggest spec |
| 40 | + erratum: "62 fractional bits" with this rationale. |
| 41 | +2. **Wider storage than the §3 struct sketch.** Spec sketches comp w_scaled |
| 42 | + as q64 and bucket scaled_sum as q128; with full-range u64 raw work those |
| 43 | + overflow. Implementation uses u128 (L0 scaled) and U256 (sums, comp |
| 44 | + scaled). Spec §5 footprint numbers shift accordingly; tightening back |
| 45 | + down requires capping w_raw (a consensus parameter decision — operator). |
| 46 | +3. **Journal does not cross epoch rebuilds.** `rewind()` refuses if the span |
| 47 | + crosses a rebuild (journal is cleared there); caller takes the full lane |
| 48 | + rebuild path — the same escape hatch as the >D case (§6.2). Affects ~D/E |
| 49 | + ≈ 1.6% of max-depth reorgs at default geometry. Suggest folding this rule |
| 50 | + into §6.2 explicitly. |
| 51 | +4. **Level sums for levels ≥ 1.** Buckets in one level can carry different |
| 52 | + epoch tags (immutability rule), so a single stored per-level scaled sum is |
| 53 | + frame-mixed; the per-band view weight is assembled per-bucket with the |
| 54 | + epoch shift (O(buckets/level) ≤ 568) instead of a maintained O(1) field. |
| 55 | + L0 sums are maintained O(1) as specced. |
| 56 | +5. **No residual dust at L = 2 (stronger than spec).** §4.2 tolerates |
| 57 | + deterministic truncation residuals between rebuilds; with the |
| 58 | + rebuild-from-raw design and default L = 2 the incremental state equals the |
| 59 | + full-scan reference EXACTLY at every operation (proven by the gate). The |
| 60 | + only residual source is the L≥3 cascade fold (children re-framed at fold); |
| 61 | + at L≥3 the gate holds at rebuild points, per spec. L≥3 needs its own |
| 62 | + rebuild-point-gated test before any chain uses it. |
| 63 | + |
| 64 | +## Stubbed / deferred (not blocking review) |
| 65 | + |
| 66 | +- **L1 view projection** (`RingFrame`/`Level` serialization for |
| 67 | + `/pplns/rings`): not implemented — view-layer concern; all backing queries |
| 68 | + exist (`payout_map`, `raw_work_in_span`, `levels()` accessor, digest). |
| 69 | +- **SoA / arena / power-of-two mask storage**: test-grade impl uses |
| 70 | + std::deque/std::vector with identical semantics; the §5 memory-layout |
| 71 | + optimizations (contiguous SoA rings, bump-allocated comps, SIMD renorm |
| 72 | + pass) are an integration-phase change that cannot alter results (same op |
| 73 | + sequence, same arithmetic). |
| 74 | +- **THE state-root hookup**: `Lane::digest()` produces the leaf; committing |
| 75 | + it into the coinbase OP_RETURN root is wiring in the existing THE |
| 76 | + commitment path, out of scope for the standalone module. |
| 77 | +- **Adaptive W (OQ-6)**: headroom only, per the resolution — W is a |
| 78 | + LaneParams constant; no formula. |
| 79 | + |
| 80 | +## Needs CI / integrator attention |
| 81 | + |
| 82 | +1. **Weight adapter**: V36 `att` is `uint288` (`target_to_average_attempts`). |
| 83 | + The lane takes `w_raw : u64`. For sharechain share targets this fits |
| 84 | + easily (att ≈ share_difficulty × 2^32), but the adapter MUST assert/clamp |
| 85 | + att ≤ u64::max — define the rule (reject share vs clamp) as a consensus |
| 86 | + parameter before wiring. Flagged rather than decided here. |
| 87 | +2. **Hashers**: `v37_hash.hpp` is a self-contained FIPS-conformant SHA-256 |
| 88 | + (known-vector tested, bit-equal to core's CSHA256). Integration may swap |
| 89 | + to `core/hash.hpp` for one less implementation; output identical. |
| 90 | +3. **Full-tree build**: `src/sharechain/CMakeLists.txt` gained |
| 91 | + `add_subdirectory(v37/test)`; the test target is dependency-free and |
| 92 | + gated on BUILD_TESTING. Not exercised against the full conan build on |
| 93 | + this VM (by design) — ci-steward/btc-heap-opt to verify. |
| 94 | +4. **gtest port**: the suite uses a standalone CHECK harness so it runs |
| 95 | + without GTest; trivially portable to the repo's gtest idiom if preferred. |
| 96 | +5. **Caller migration**: `HeadPPLNS`/`think()` integration (replacing |
| 97 | + `DensePPLNSRing` per the spec's "subsumes" map) is intentionally not |
| 98 | + started — the module is per-coin-agnostic and caller-shaped for it |
| 99 | + (push/rewind/payout_map mirror slide/rebuild/compute_v36_weights). |
0 commit comments