blockyard 0.0.9 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +251 -1
- package/README.md +42 -23
- package/bin/blockyard.js +2 -1
- package/docs/API.md +16 -14
- package/docs/ARCHITECTURE.md +92 -5
- package/docs/CONFIGURATION.md +33 -26
- package/docs/GETTING-STARTED.md +5 -2
- package/docs/INSTALL.md +90 -33
- package/docs/MEASUREMENTS.md +147 -0
- package/docs/SECURITY.md +32 -15
- package/docs/TROUBLESHOOTING.md +35 -1
- package/docs/USER-GUIDE.md +266 -26
- package/package.json +1 -1
- package/public/404.html +1 -1
- package/public/css/app.css +306 -82
- package/public/donate-qr.png +0 -0
- package/public/index.html +295 -103
- package/public/js/agents.js +228 -51
- package/public/js/app.js +82 -8
- package/public/js/blockscene3d.js +179 -27
- package/public/js/charts.js +21 -21
- package/public/js/depthchart.js +31 -27
- package/public/js/details3d.js +1456 -71
- package/public/js/doom.js +31 -0
- package/public/js/dosaudio.js +48 -0
- package/public/js/dosgame.js +389 -0
- package/public/js/dosio.js +186 -0
- package/public/js/dospc.js +1353 -0
- package/public/js/dosworker.js +196 -0
- package/public/js/login.js +5 -0
- package/public/js/markets.js +46 -8
- package/public/js/mining.js +310 -32
- package/public/js/panels.js +14 -10
- package/public/js/pricechart.js +14 -13
- package/public/js/quake.js +20 -0
- package/public/js/settings.js +103 -21
- package/public/js/soundcard.js +459 -0
- package/public/js/theme.js +235 -0
- package/public/js/wolf3d.js +22 -0
- package/public/js/x86.js +1978 -0
- package/scripts/donate-qr.py +12 -9
- package/scripts/dos-bench.js +56 -0
- package/scripts/setup.js +34 -12
- package/scripts/shots.mjs +6 -0
- package/scripts/smoke.sh +1 -1
- package/scripts/tls.js +31 -0
- package/server/chain/index/build.js +21 -4
- package/server/collect/monitor.js +30 -1
- package/server/collect/network.js +295 -0
- package/server/config.js +46 -22
- package/server/http/api.js +49 -5
- package/server/http/games.js +77 -0
- package/server/http/server.js +8 -0
- package/server/main.js +53 -8
- package/server/tls/selfsigned.js +160 -0
- package/systemd/blockyard.service +7 -5
- package/docs/PRIVATE-LEADERBOARD.md +0 -230
- package/docs/STATE-2026-09-09.md +0 -200
package/docs/MEASUREMENTS.md
CHANGED
|
@@ -1252,3 +1252,150 @@ showing STALLED. Block intervals are close to exponential with a 10-minute mean,
|
|
|
1252
1252
|
minutes or more has probability e^-4, about 1.8% -- once in fifty blocks, a few times a day. Stalled
|
|
1253
1253
|
now means a connected peer reports a higher tip (`getpeerinfo` `synced_headers`); peers agreeing on
|
|
1254
1254
|
the tip is a long gap and synced; no peer height at all waits two hours.
|
|
1255
|
+
|
|
1256
|
+
## 32. The DOOM Diversion's emulated PC (2026-09-15)
|
|
1257
|
+
|
|
1258
|
+
Not the node: the i386 and the PC in `public/js/x86.js` and `dospc.js` running the shareware
|
|
1259
|
+
`DOOM.EXE` v1.9 (the Diversion). Taken on this box -- AMD Ryzen 9 9950X3D, Node v22.23.2, Chromium
|
|
1260
|
+
152 (snap, headless). Reproduce the headless figures with `node scripts/dos-bench.js doom`.
|
|
1261
|
+
|
|
1262
|
+
**Speed of the interpreter**, 400 M instructions of DOOM's title and demos on a clock of 30 M
|
|
1263
|
+
instructions to the virtual second:
|
|
1264
|
+
|
|
1265
|
+
| build | instructions a second |
|
|
1266
|
+
|---|---|
|
|
1267
|
+
| first cut: unsigned values (`>>> 0`), flag operands in closure variables, a try/catch per instruction | 66-68 M |
|
|
1268
|
+
| every value an int32, lazy flags in an `Int32Array`, one try/catch around the loop, 32-bit fast paths | 95 M |
|
|
1269
|
+
| the same with the Sound Blaster and OPL3 attached, synthesising at 44.1 kHz per call of `tick` | 73 M |
|
|
1270
|
+
| the OPL's per-register work hoisted out of the sample loop | 82 M |
|
|
1271
|
+
| `tick` working in batches of at least 128 frames (it had been called every 2,000 instructions: a sample or two each) | **92 M** |
|
|
1272
|
+
|
|
1273
|
+
The try/catch alone was 14% of the profile, and the collector 1.5% from doubles boxed in closure
|
|
1274
|
+
variables; the rewrite was checked instruction by instruction against the first cut for 40 M
|
|
1275
|
+
instructions (identical except the start-up's environment read, which the first cut got wrong).
|
|
1276
|
+
|
|
1277
|
+
**In the browser**, the machine in a worker, sound on: **94-110 M instructions a second, 34-37
|
|
1278
|
+
frames a second** -- DOOM's own cap is 35. The game needs about a million instructions a frame of
|
|
1279
|
+
real work; the rest of each tic it spends in its own busy wait for the timer. The page's CSP forbids
|
|
1280
|
+
eval, so a JIT was never an option; a slower machine than this one has roughly a factor of two in
|
|
1281
|
+
hand before DOOM drops below 35.
|
|
1282
|
+
|
|
1283
|
+
**Start-up**: graphics mode after 8.0 M instructions without a sound card, 17.0 M with one (the
|
|
1284
|
+
DMX driver probes the DSP and the OPL); 20 pages flipped by 31 M.
|
|
1285
|
+
|
|
1286
|
+
**Correctness of the CPU, measured against the host's own**: a differential fuzzer ran random
|
|
1287
|
+
instructions natively (a C harness in 64-bit mode, 32-bit operands, register forms) and in `x86.js`,
|
|
1288
|
+
comparing all registers and every flag the instruction defines -- ALU rows, immediates, shifts and
|
|
1289
|
+
rotates with counts past the width, MUL/IMUL/DIV/IDIV including divide faults, BT/BTS/BTR/BTC,
|
|
1290
|
+
BSF/BSR, SHLD/SHRD, MOVZX/MOVSX, SETcc, BSWAP, XADD, CMPXCHG, SAHF/LAHF. Two seeds, 78,565
|
|
1291
|
+
instructions, 2,338 divide faults agreed, **zero mismatches**. The harness needs a C compiler, so it
|
|
1292
|
+
is not in `npm test`; `test/x86.test.js` keeps a case from each class it covered.
|
|
1293
|
+
|
|
1294
|
+
**The music is in tune**: over 10 s of the title music, 178 notes keyed on, 96 of them within
|
|
1295
|
+
2.5 cents of equal temperament; the rest spread to +-50 cents, which is DMX's pitch bends.
|
|
1296
|
+
|
|
1297
|
+
## 33. Quake on the same PC (2026-09-15)
|
|
1298
|
+
|
|
1299
|
+
`QUAKE.EXE` v1.06 (DJGPP, go32 stub) on the emulated PC, this box, Node v22.23.2. Reproduce with
|
|
1300
|
+
`node scripts/dos-bench.js quake`.
|
|
1301
|
+
|
|
1302
|
+
**Speed**: 77 M instructions a second headless with the Sound Blaster attached, 72-79 in a Chromium
|
|
1303
|
+
worker -- lower than DOOM's 90-105 because Quake's code is FPU-heavy (the x87 was 15% of the profile)
|
|
1304
|
+
and every memory operand adds a segment base (DJGPP's DS is at its memory block; `ea` was 13%).
|
|
1305
|
+
Moving the FPU stack to a Float64Array with typed-array operand conversion and one base addition
|
|
1306
|
+
when DS and SS share it took 74 to 76: the interpreter's dispatch is the rest.
|
|
1307
|
+
|
|
1308
|
+
**Frame rate**: `+timedemo demo1` on a clock of 74 M instructions to the virtual second -- the
|
|
1309
|
+
emulator's own speed -- reported **969 frames in 33.5 seconds, 28.9 fps**, about 2.6 M instructions a
|
|
1310
|
+
frame. In the browser, a new game on the start map drew 26 frames a second. Period hardware for
|
|
1311
|
+
comparison: a Pentium 90 ran the same demo at 320x200 at roughly that rate.
|
|
1312
|
+
|
|
1313
|
+
**Start-up**: graphics mode after 244 M instructions on a 30 M clock (Quake pages its 27 MB heap in
|
|
1314
|
+
and times its hardware), twenty screens drawn by 285 M; 2.8 s of wall time headless.
|
|
1315
|
+
|
|
1316
|
+
## 34. The decoded-instruction cache, and Quake's view size (2026-09-15)
|
|
1317
|
+
|
|
1318
|
+
This box, Node v22.23.2, `node scripts/dos-bench.js doom 400` / `quake 1500` (M instructions a
|
|
1319
|
+
second, headless, Sound Blaster attached):
|
|
1320
|
+
|
|
1321
|
+
| build | DOOM | Quake |
|
|
1322
|
+
|---|---|---|
|
|
1323
|
+
| before (the interpreter, §32-33) | 90 | 77 |
|
|
1324
|
+
| a closure per decoded instruction | 68 | 69 |
|
|
1325
|
+
| int32 decodings in a typed array per page, one switch; a write drops the whole page | 83 | 90 |
|
|
1326
|
+
| ...a write clears only the instructions it overlaps (DOOM patches its span drawer each call) | 100 | 90 |
|
|
1327
|
+
| ...the FPU decoded too, and the loop keeps the current page between instructions | 107 | 104 |
|
|
1328
|
+
| ...no page check after a cached handler | **111** | **108** |
|
|
1329
|
+
|
|
1330
|
+
The page-drop row is the one to remember: 217,660 whole-page drops in 300 M instructions of DOOM,
|
|
1331
|
+
every one from `mov [eax],ebx` into the constants of its own span routine at 0x12bdaf.
|
|
1332
|
+
|
|
1333
|
+
**Quake's view size**, `+viewsize N +timedemo demo1` (969 frames), on a clock set to the emulator's
|
|
1334
|
+
speed:
|
|
1335
|
+
|
|
1336
|
+
| viewsize | before the cache (76 M clock) | after (105 M clock) |
|
|
1337
|
+
|---|---|---|
|
|
1338
|
+
| 100 | 29.7 fps | 40.9 fps |
|
|
1339
|
+
| 80 (the new default) | 32.5 | 44.7 |
|
|
1340
|
+
| 60 | 40.5 | -- |
|
|
1341
|
+
|
|
1342
|
+
In a Chromium worker: Quake 99-106 MIPS and 40-42 frames a second in a new game at `viewsize 80`
|
|
1343
|
+
(26 before), DOOM 133 MIPS at its 35 fps cap.
|
|
1344
|
+
|
|
1345
|
+
**Checked, not assumed**: both games lock-stepped against the uncached interpreter (DOOM 400 M, Quake
|
|
1346
|
+
1.5 G instructions; registers and flags compared every 10,000; memory identical at the end), and the
|
|
1347
|
+
native fuzzer re-run through `run(1)` over 118k instructions with no mismatch.
|
|
1348
|
+
|
|
1349
|
+
## 35. A second pass on the CPU: what paid and what did not (2026-09-15)
|
|
1350
|
+
|
|
1351
|
+
Asked for all five of: split the ALU routine, specialise the hot x87 forms, cheaper dispatch, dead
|
|
1352
|
+
flags, and a block copy of the frame into video memory. **Method, after the first readings misled:**
|
|
1353
|
+
each build against a copy of the previous one (`oracle4`), pinned to one core with `taskset`, best of
|
|
1354
|
+
three; unpinned runs on this shared box moved +-5% between identical runs. Quake throughput as M
|
|
1355
|
+
instructions a second over its timedemo, and as **frames a second of wall time** over 600 timedemo
|
|
1356
|
+
frames -- the second catches work a MIPS figure cannot, such as a `rep movsd` that is one instruction
|
|
1357
|
+
however many bytes it moves. DOOM on `-timedemo demo1` only: its normal MIPS depends on how much time
|
|
1358
|
+
lands in its cheap wait loop, which a change to the machine's slice size alone moved by 5%.
|
|
1359
|
+
|
|
1360
|
+
| build | Quake MIPS | Quake fps (wall) | DOOM timedemo MIPS |
|
|
1361
|
+
|---|---|---|---|
|
|
1362
|
+
| before (the cache, §34) | 101 | 37.7 | 103 |
|
|
1363
|
+
| ALU split per operation + hot x87 forms decoded to their own handlers | 133 | -- | -- |
|
|
1364
|
+
| + fused cmp/test+Jcc dispatch and "no flags" forms by flag liveness | 131 | -- | 110 |
|
|
1365
|
+
| the same without the look-ahead (fusion and no-flags off) | 133 | -- | 114.5 |
|
|
1366
|
+
| + the address formed inline in the loop instead of a call per handler | 141.5 | -- | 112 |
|
|
1367
|
+
| + aligned reads/writes inline in the hottest moves | 141 | 52.5 | 115 |
|
|
1368
|
+
| the same without the VGA block copy | 141 | 51 (noise) | -- |
|
|
1369
|
+
|
|
1370
|
+
**Kept**: the ALU split, the x87 handlers, the inline address and moves -- Quake's frames a second of
|
|
1371
|
+
wall time 37.7 -> 52.5 (+40%). **Removed**: the fused branches and the no-flags forms (nothing gained;
|
|
1372
|
+
the look-ahead re-ran on every re-decode of DOOM's self-patching drawer), and the block copy (within
|
|
1373
|
+
noise: the frame copy is 64,000 bytes against 140 M instructions a second).
|
|
1374
|
+
|
|
1375
|
+
The reason inlining mattered: `run()` is one function with 170-odd cases, V8's cumulative inlining
|
|
1376
|
+
budget runs out long before the helpers it calls, and every uninlined `eaOf` was a real call.
|
|
1377
|
+
|
|
1378
|
+
**In a Chromium worker** (new game, `viewsize 80`): Quake 115-118 MIPS and 39-49 frames a second on
|
|
1379
|
+
screen, once the worker looked for a finished frame every 50,000 instructions instead of once per
|
|
1380
|
+
10 ms slice (two frame copies inside one slice had been showing as one). DOOM 139 MIPS.
|
|
1381
|
+
|
|
1382
|
+
Checked: DOOM 400 M and Quake 1.5 G instructions lock-stepped identical to `oracle4` (memory equal),
|
|
1383
|
+
and the native fuzzer through `run(1)`, 78k instructions, no mismatch.
|
|
1384
|
+
|
|
1385
|
+
## 36. Wolfenstein 3D in real mode (2026-09-15)
|
|
1386
|
+
|
|
1387
|
+
`WOLF3D.EXE` v1.4 (LZEXE-packed, Borland C, real mode) on the emulated PC, this box, Node v22.23.2,
|
|
1388
|
+
pinned to one core. It unpacks itself and reaches the sign-on screen in 1.0 s of wall time (60 M
|
|
1389
|
+
instructions on a 20 M clock).
|
|
1390
|
+
|
|
1391
|
+
**Speed**: in a game, turning on the first map, **65 M instructions a second** headless (twice the same
|
|
1392
|
+
reading) and 68-69 in a Chromium worker. Real-mode code runs through the uncached `step()`, so this is
|
|
1393
|
+
the plain interpreter's speed; the game needs about **285 k instructions a frame**, so its 70 frames a
|
|
1394
|
+
second (the VGA's refresh, which it waits for) take 20 M a second -- a third of what is there, and the
|
|
1395
|
+
browser shows 70 frames a second.
|
|
1396
|
+
|
|
1397
|
+
**DOOM and Quake unchanged**: best of three against a copy of the previous build (`oracle5`), DOOM
|
|
1398
|
+
timedemo 93.3 vs 93.0 M a second, Quake 126.3 vs 127.7. Quake lock-stepped identical for 600 M
|
|
1399
|
+
instructions, memory equal. DOOM lock-steps identical to 175 M and then differs, by design: at 173 M it
|
|
1400
|
+
copies between VGA pages in write mode 1, which the previous build wrote as plain data, and reads the
|
|
1401
|
+
planes back.
|
package/docs/SECURITY.md
CHANGED
|
@@ -5,7 +5,7 @@ page describes the access model, what protects it, and exactly what leaves your
|
|
|
5
5
|
To report a vulnerability, see [SECURITY.md](../SECURITY.md) at the repository root.
|
|
6
6
|
|
|
7
7
|
- [Threat model in one paragraph](#threat-model-in-one-paragraph)
|
|
8
|
-
- [Access:
|
|
8
|
+
- [Access: sign-in by default, open on request](#access-sign-in-by-default-open-on-request)
|
|
9
9
|
- [Accounts, sessions and passwords](#accounts-sessions-and-passwords)
|
|
10
10
|
- [Talking to the node](#talking-to-the-node)
|
|
11
11
|
- [Node writes](#node-writes)
|
|
@@ -26,10 +26,19 @@ monitor leaking information about you to third parties (limited to the on-demand
|
|
|
26
26
|
connections listed below, which you can turn off). The monitor does not hold keys and has no
|
|
27
27
|
wallet access.
|
|
28
28
|
|
|
29
|
-
## Access:
|
|
29
|
+
## Access: sign-in by default, open on request
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
**Out of the box the monitor listens on `127.0.0.1` only and requires sign-in.** The first
|
|
32
|
+
start creates an `admin` account and prints its password once (or takes it from
|
|
33
|
+
`BLOCKYARD_ADMIN_PASSWORD`). Reach it from another machine over an SSH tunnel
|
|
34
|
+
(`ssh -L 21000:127.0.0.1:21000 you@host`), or bind a LAN address with `BLOCKYARD_BIND` /
|
|
35
|
+
`server.hosts` once you have decided who may see it. These are the defaults since
|
|
36
|
+
2026-09-15; 0.0.9 shipped bound to every interface with no sign-in, which the first outside
|
|
37
|
+
review rightly called out.
|
|
38
|
+
|
|
39
|
+
Open access is still available as a posture you choose: with `auth.enabled: false`
|
|
40
|
+
(`BLOCKYARD_AUTH=0`), anyone who can reach the port reads the monitor with the fixed role
|
|
41
|
+
`viewer`:
|
|
33
42
|
|
|
34
43
|
| open to anyone who can reach the port | still closed |
|
|
35
44
|
|---|---|
|
|
@@ -42,7 +51,7 @@ The `viewer` ceiling cannot be raised by configuration or by any credential whil
|
|
|
42
51
|
are off. The start-up log states which addresses are readable and how to close them, so
|
|
43
52
|
"anyone on the LAN can read your node" is never a surprise.
|
|
44
53
|
|
|
45
|
-
|
|
54
|
+
With sign-in on (the default; `BLOCKYARD_AUTH=1` restores it after an override), roles:
|
|
46
55
|
|
|
47
56
|
| role | may |
|
|
48
57
|
|---|---|
|
|
@@ -124,9 +133,15 @@ Every call and every refusal is appended to the audit trail.
|
|
|
124
133
|
|
|
125
134
|
## Transport security
|
|
126
135
|
|
|
127
|
-
- HTTPS is
|
|
128
|
-
|
|
129
|
-
|
|
136
|
+
- HTTPS is the default on **every** listener. With no certificate named, the server makes its
|
|
137
|
+
own self-signed one on first start (`server/tls/selfsigned.js`, under `<data>/tls/`, the key
|
|
138
|
+
mode 600, ECDSA P-256), naming the addresses it is reached on, and remakes it when it nears
|
|
139
|
+
expiry or stops naming a bound address; the log prints its fingerprint. A certificate of your
|
|
140
|
+
own replaces it (`BLOCKYARD_TLS_CERT`/`_KEY`); a half-configured pair or an expired
|
|
141
|
+
certificate stops the start-up. `BLOCKYARD_TLS=0` is plain HTTP, for a proxy in front.
|
|
142
|
+
- A self-signed certificate proves nothing about who you are talking to the first time; it
|
|
143
|
+
does encrypt the session and pins the fingerprint after that. Compare the fingerprint the
|
|
144
|
+
log prints with the one the browser shows before trusting it on a network you do not own.
|
|
130
145
|
- Over HTTPS the session cookie is `Secure` and `Strict-Transport-Security` is sent with a
|
|
131
146
|
two-day lifetime, without `includeSubDomains` or `preload` — a LAN address can be reissued,
|
|
132
147
|
and HSTS cannot be withdrawn once a browser has it.
|
|
@@ -150,13 +165,15 @@ Everything in the monitor talks only to your node, **except**:
|
|
|
150
165
|
|
|
151
166
|
| when | to | what is sent |
|
|
152
167
|
|---|---|---|
|
|
153
|
-
| while someone has the **Markets**, **Kiosk** or **Overview** tab open — Overview's price line
|
|
154
|
-
| when someone opens an **explorer** page and no fresh market price is at hand | two of the exchanges above, at most once a minute | a public ticker request |
|
|
168
|
+
| only with **Enable market polling** ticked in Display settings (**off by default**), while someone has the **Markets**, **Kiosk** or **Overview** tab open — Overview's price line reads the same feed unless you switch it off — and for 10 minutes after the last request | `api.exchange.coinbase.com`, `api.kraken.com`, `www.bitstamp.net`, `api-pub.bitfinex.com`, `www.okx.com` (HTTPS) | public ticker, hourly candle and order-book requests with a `User-Agent` naming the software — nothing about your node |
|
|
169
|
+
| with polling on, when someone opens an **explorer** page or the **Mining** tab and no fresh market price is at hand | two of the exchanges above, at most once a minute | a public ticker request |
|
|
155
170
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
171
|
+
**Out of the box none of this happens**: polling is off until someone ticks **Display settings → Markets & Price → Enable market polling**, and until then the
|
|
172
|
+
Markets and Kiosk tabs say so and the explorer shows no dollar figures. The switch is a Display
|
|
173
|
+
setting shared by every screen, so anyone who can change settings on this monitor can turn it
|
|
174
|
+
on; `BLOCKYARD_MARKETS=0` (or `"markets": { "enabled": false }`) removes the feed from the
|
|
175
|
+
server so that no checkbox can. With polling on, nothing is fetched when nobody is looking. Your machine's public address is visible to those exchanges
|
|
176
|
+
when a request is made, as with any web request.
|
|
160
177
|
|
|
161
178
|
The monitor sends no telemetry, checks for no updates, and phones home to no one.
|
|
162
179
|
|
|
@@ -190,6 +207,6 @@ and errors; they never contain passwords, session tokens or RPC credentials.
|
|
|
190
207
|
- Turn accounts on if anyone who can reach the port should not see your node.
|
|
191
208
|
- Use HTTPS, a reverse proxy, or an SSH tunnel on untrusted networks.
|
|
192
209
|
- Leave node actions off unless you have a specific need, and then enable only that action.
|
|
193
|
-
- Set `BLOCKYARD_MARKETS=0` on machines that must not make outbound connections.
|
|
210
|
+
- Set `BLOCKYARD_MARKETS=0` on machines that must not make outbound connections: the polling checkbox (off by default) then cannot turn the feed on.
|
|
194
211
|
- Keep `config/local.json` and `data/` readable only by the service account.
|
|
195
212
|
- Keep Node.js current within the 22.x line or later.
|
package/docs/TROUBLESHOOTING.md
CHANGED
|
@@ -54,6 +54,10 @@ The Node & RPC page shows the last error. Common causes:
|
|
|
54
54
|
|
|
55
55
|
## The page does not load from another machine
|
|
56
56
|
|
|
57
|
+
0. Out of the box the monitor binds `127.0.0.1` and answers this machine only. Either reach
|
|
58
|
+
it over an SSH tunnel (`ssh -L 21000:127.0.0.1:21000 you@host`, then `https://localhost:21000`)
|
|
59
|
+
or bind a LAN address: `BLOCKYARD_BIND=192.0.2.10` (or `0.0.0.0`), or `server.hosts` in
|
|
60
|
+
`config/local.json`, and restart.
|
|
57
61
|
1. From the other machine, check how it reaches the server: `ip route get <address>`.
|
|
58
62
|
2. Make sure that address is one the monitor binds — see the start-up log. A LAN-only bind is
|
|
59
63
|
not reachable over a VPN unless the VPN address is also listed in `server.host`.
|
|
@@ -159,6 +163,14 @@ so far and an ETA; the address page repeats it. Things it says, and what they me
|
|
|
159
163
|
[INSTALL](INSTALL.md#bitcoinconf-settings-worth-having), or let it run overnight.
|
|
160
164
|
- **The ETA is wrong at first** — it is computed from the files done so far in the current phase
|
|
161
165
|
and settles after the first few; files are not all the same size.
|
|
166
|
+
- **It stopped one short — "scan 5,720 of 5,721, about 1 s left" for an hour** — a worker
|
|
167
|
+
died, most likely killed for memory (four workers is about 10 GB beside the node). Since
|
|
168
|
+
2026-09-15 that fails the build at once with `an index worker exited with code N while on
|
|
169
|
+
{"type":"scan","file":...}` and the flag turns to *build failed*; before that fix the build
|
|
170
|
+
hung there for good. Either way: restart BlockYard with fewer workers (`addressIndexWorkers` on
|
|
171
|
+
the node entry in `config/local.json`). The build starts over; it is not resumable. The flag
|
|
172
|
+
also says **no progress for N min** whenever nothing has moved for two minutes, so a stall is
|
|
173
|
+
visible as one rather than as a stale ETA.
|
|
162
174
|
- **Hours, not minutes** — expect **a few hours**: 29 min 45 s is 16 workers on NVMe, and four
|
|
163
175
|
workers (the installer's default) are roughly four times slower; **spinning disks** are slower still whatever the
|
|
164
176
|
number, and there one worker is the fast setting, because parallel readers only seek against
|
|
@@ -171,9 +183,25 @@ so far and an ETA; the address page repeats it. Things it says, and what they me
|
|
|
171
183
|
restart (the server builds again), or run `node scripts/index-build.js --out <dir>` by hand.
|
|
172
184
|
A pruned node, unreadable block files and a full disk are the usual causes.
|
|
173
185
|
|
|
186
|
+
## "getrawmempool verbose dropped as stale" in Events, and the mempool panels look old
|
|
187
|
+
|
|
188
|
+
The monitor keeps one RPC request in flight and serves the live polls first; the full-pool poll is
|
|
189
|
+
the lowest priority, so when the node's RPC is slow it waits behind them and, past its freshness
|
|
190
|
+
budget, is dropped rather than shown as current. A streak of drops is one warning event when it
|
|
191
|
+
starts, a counter on **Node & RPC → data quality** while it lasts, and one event when the poll
|
|
192
|
+
answers again with the count and the span. The Mempool, Block space and Mining panels show their
|
|
193
|
+
last reading meanwhile and say how old it is.
|
|
194
|
+
|
|
195
|
+
The cause is the node, not the monitor: look for what else is asking it. On 2026-09-15 an Umbrel
|
|
196
|
+
node answered in seconds for thirteen hours while another BlockYard built its address index
|
|
197
|
+
against it over the LAN, and the drops stopped the moment that build finished. A remote index
|
|
198
|
+
build, a wallet rescan, `gettxoutsetinfo` from another tool, or an initial block download all
|
|
199
|
+
show the same way.
|
|
200
|
+
|
|
174
201
|
## Markets or Kiosk show no prices
|
|
175
202
|
|
|
176
|
-
- **"market
|
|
203
|
+
- **"market polling is off"** — the default. Tick **Display settings → Markets & Price → Enable market polling**.
|
|
204
|
+
- **"market data is off on this server"** — `BLOCKYARD_MARKETS=0` or `markets.enabled: false` is set on the server; the checkbox cannot override it.
|
|
177
205
|
- **"asking the exchanges…" for a long time** — the server cannot reach the exchanges. Test
|
|
178
206
|
from the server: `curl -sI https://api.exchange.coinbase.com/products/BTC-USD/ticker`. Check
|
|
179
207
|
outbound firewall rules and DNS.
|
|
@@ -289,6 +317,12 @@ browser in kiosk mode pointed at `http://<host>:21000/#kiosk`.
|
|
|
289
317
|
- **"too many attempts"** — the lockout lasts 10 minutes per username and per address.
|
|
290
318
|
- **Sign-in does not stick** — over plain HTTP, make sure `BLOCKYARD_SECURE_COOKIE` is not set
|
|
291
319
|
(a `Secure` cookie is never sent over HTTP). Behind a TLS proxy, set it.
|
|
320
|
+
- **The browser warns about the certificate** — expected once per address: the monitor's own
|
|
321
|
+
certificate is self-signed. Compare the fingerprint in the start-up log with the browser's,
|
|
322
|
+
then accept it. To be rid of the warning, name a certificate of your own (INSTALL §9) or put
|
|
323
|
+
a proxy with a real one in front (§10).
|
|
324
|
+
- **`https://` says the connection was reset, or `http://` shows nothing** — the port speaks
|
|
325
|
+
one or the other: HTTPS unless `BLOCKYARD_TLS=0`. Use the scheme the start-up log prints.
|
|
292
326
|
|
|
293
327
|
## Tests fail on a fresh clone
|
|
294
328
|
|