| … | … | @@ -3266,7 +3266,50 @@ injected per layer: |
| 3266 | 3266 | (m5g1*, m5g2*, m5g3e3, m5g4e1/e2, m5f*). |
| 3267 | 3267 | - **R3c:** what rt newly makes portable: `RandomIterator` (`rt::random` = `Math.random`) |
| 3268 | 3268 | and `queueUpdateAll`'s ≥ 40-peer path with `_updateAllBump` |
| 3269 | | (`setTimeout(updateAll, getUpdateAllDelay)`). Gate designed when R3b is done. |
| 3269 | (`setTimeout(updateAll, getUpdateAllDelay)`). Designed 2026-10-05, after R3b (below). |
| 3270 | - **R3c DESIGN (2026-10-05; gate choice: the user's).** |
| 3271 | - **Why it changes behaviour, not only randomness.** random-array-iterator 1.0.0 SWAPS |
| 3272 | elements of the array it walks. JS reorders `peers`, `_queued` and `_ranges` on every |
| 3273 | walk, even with `Math.random` pinned to 0 (`[a, b, c]` walks a, c, b and stays permuted), |
| 3274 | and `dequeue` is a swap-with-last pop. keetd walks in order and erases in order. Order |
| 3275 | decides which peer gets a request, which queued block goes first, and which ranges |
| 3276 | `_updateRanges` (index-based) checks. |
| 3277 | - **Ported:** |
| 3278 | - `repl/include/hc/random_iterator.h`: random-array-iterator 1.0.0 over a |
| 3279 | `std::vector<T>&`, mutating: `next` (index `start + (rt::random() * length) | 0`), |
| 3280 | `dequeue`, `requeue`, `restart`; |
| 3281 | - `updateAll(all = true)`: both peer loops through one iterator (`requeue` on true, |
| 3282 | `restart()` between them), `limit = all ? peers.length : MIN_PEER_UPDATE_ALL`, and a |
| 3283 | full scan clears `_updateAllBump`; `updateSubset() = updateAll(false)`; |
| 3284 | - `queueUpdateAll`: below 40 peers `updateAll()`; else `updateSubset()` plus one |
| 3285 | `_updateAllBump = setTimeout(updateAll, getUpdateAllDelay(peers))`, where the delay is |
| 3286 | `min(3000, max(100, (n - 40) * 5))`. `destroy` clears it; |
| 3287 | - `_updatePeer`'s `_queued` walk and `_updatePeerNonPrimary`'s `_ranges` walk through the |
| 3288 | iterator, with `dequeue`; |
| 3289 | - the four `Math.floor(Math.random() * len)` offsets (seek, range, block batch, want); |
| 3290 | - `NOT_DOWNLOADING_SLACK`: once per process, from `rt::random()` on first use. |
| 3291 | - **rt:** the Virtual runtime takes a random SOURCE (a function), not only a constant. The |
| 3292 | Real runtime can be pinned (a function), for gates whose JS peer pins `Math.random`. |
| 3293 | - **Gate:** |
| 3294 | - **Iterator:** `vectors/data/random-iterator.json`, from a bare script over the real |
| 3295 | module: op sequences (next / requeue / dequeue / restart) over arrays, with |
| 3296 | `Math.random` from a fixed list. The port must yield the same values and leave the same |
| 3297 | array. |
| 3298 | - **Scan (the stub-peer transcript):** a bare script drives hypercore 11.37's own |
| 3299 | `Replicator.prototype` `updateAll` / `updateSubset` / `queueUpdateAll` / |
| 3300 | `getUpdateAllDelay` on a stub `this`: N peers (3, 39, 40, 41, 80), `_updatePeer` and |
| 3301 | `_updatePeerNonPrimary` answering from a seeded script, `_maybeUpdate`, `_ranges` and |
| 3302 | `_reorgs` set per step, timers on a pinned clock, `Math.random` from a seeded |
| 3303 | sequence. It records every call (`_updatePeer(p)`, `_updatePeerNonPrimary(p)`, |
| 3304 | `_checkUpgradeIfAvailable`) and every bump armed, cleared or fired. keetd replays the |
| 3305 | same scenarios on a test subclass of `Replicator` whose four callees are overridden. |
| 3306 | Those callees become `virtual`, the C++ form of the JS stub; the scan logic under test |
| 3307 | is the real one. Real `Peer`s are used, built without a mux. |
| 3308 | - **m3c:** the Real runtime is pinned to 0, as the JS peers are (`deterministic`). Every |
| 3309 | scenario must stay green while now running through the swapping iterator. |
| 3310 | - **Drill `r3c`:** the iterator (no swap, no requeue, restart keeps `start`), the scan |
| 3311 | (no limit, no requeue, a full scan keeps the bump), the bump (wrong clamp, `destroy` |
| 3312 | leaves it), and the offsets (always 0). |
| 3270 | 3313 | - **NOT R3 (R4):** every `await` — `seeker.update`, storage, and `yieldToLoop` (it needs the |
| 3271 | 3314 | same continuation-style `_updateNonPrimary`). |
| 3272 | 3315 | - **R3a DONE 2026-10-04** (keetd 4cf2283). Every driver runs on rt; ctest 69/69. |