Skip to content

Commit 90488a9

Browse files
authored
Merge pull request #84 from frstrtr/v37/mrr-roundabout-buffer
sharechain/v37: MRR roundabout round-buffer base library
2 parents eddb766 + 7cc02f3 commit 90488a9

11 files changed

Lines changed: 1570 additions & 3 deletions

File tree

.github/workflows/build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ jobs:
6767
test_mweb_builder \
6868
test_address_resolution test_compute_share_target \
6969
test_utxo \
70+
v37_test \
7071
-j$(nproc)
7172
7273
- name: Run tests
@@ -192,6 +193,7 @@ jobs:
192193
test_address_resolution test_compute_share_target \
193194
test_utxo \
194195
test_coin_broadcaster test_multiaddress_pplns test_pplns_stress \
196+
v37_test \
195197
-j$(nproc)
196198
197199
- name: Run tests under sanitizers

src/sharechain/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ set(SHARECHAIN_SOURCE
1111
add_library(sharechain OBJECT ${SHARECHAIN_SOURCE})
1212
target_link_libraries(sharechain core)
1313

14-
add_subdirectory(test)
14+
add_subdirectory(test)
15+
add_subdirectory(v37/test)
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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).
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# V37 MRR roundabout — standalone unit tests.
2+
# Header-only module, stdlib-only: no gtest, no core link needed. The suite
3+
# is its own harness (returns nonzero on failure) so it runs anywhere the
4+
# toolchain exists, including outside the conan/boost dependency tree.
5+
if (BUILD_TESTING)
6+
add_executable(v37_test v37_test.cpp)
7+
target_compile_features(v37_test PRIVATE cxx_std_20)
8+
add_test(NAME v37_test COMMAND v37_test)
9+
endif()

0 commit comments

Comments
 (0)