blockyard 0.0.1 → 0.0.9
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 +679 -0
- package/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +172 -4
- package/SECURITY.md +38 -0
- package/bin/blockyard.js +40 -0
- package/config/pool-map.json +2620 -0
- package/docs/API.md +1575 -0
- package/docs/ARCHITECTURE.md +1307 -0
- package/docs/AUTO-UPDATE.md +269 -0
- package/docs/CONFIGURATION.md +840 -0
- package/docs/DEFECTS.md +813 -0
- package/docs/EFFECTS-AGENTS.md +448 -0
- package/docs/GETTING-STARTED.md +202 -0
- package/docs/INSTALL.md +490 -0
- package/docs/MEASUREMENTS.md +1254 -0
- package/docs/PRIVATE-LEADERBOARD.md +230 -0
- package/docs/RULES.md +681 -0
- package/docs/SECURITY-AUDIT-2026-09-14.md +177 -0
- package/docs/SECURITY-AUDIT.md +258 -0
- package/docs/SECURITY.md +195 -0
- package/docs/STATE-2026-09-09.md +200 -0
- package/docs/TROUBLESHOOTING.md +298 -0
- package/docs/USER-GUIDE.md +1022 -0
- package/package.json +53 -5
- package/public/404.html +9 -0
- package/public/css/app.css +1785 -0
- package/public/index.html +893 -0
- package/public/js/about.js +112 -0
- package/public/js/agents.js +964 -0
- package/public/js/app.js +1312 -0
- package/public/js/arkanoid.js +806 -0
- package/public/js/blockanoid.js +347 -0
- package/public/js/blockout.js +347 -0
- package/public/js/blockpack.js +428 -0
- package/public/js/blockscene3d.js +2678 -0
- package/public/js/breakout.js +224 -0
- package/public/js/charts.js +635 -0
- package/public/js/depthchart.js +311 -0
- package/public/js/details3d.js +2957 -0
- package/public/js/explorer.js +405 -0
- package/public/js/feepalette.js +149 -0
- package/public/js/fmt.js +162 -0
- package/public/js/goggles.js +886 -0
- package/public/js/kiosk.js +41 -0
- package/public/js/login.js +83 -0
- package/public/js/markets.js +357 -0
- package/public/js/mining.js +1138 -0
- package/public/js/panels.js +966 -0
- package/public/js/pricechart.js +188 -0
- package/public/js/settings.js +1014 -0
- package/public/js/tetris.js +226 -0
- package/public/js/tetrust.js +356 -0
- package/public/js/tetsound.js +175 -0
- package/public/login.html +33 -0
- package/scripts/blockfile-measure.js +156 -0
- package/scripts/browser-check.mjs +286 -0
- package/scripts/check.js +173 -0
- package/scripts/decode-check.js +81 -0
- package/scripts/doc-counts.js +109 -0
- package/scripts/donate-qr.py +20 -0
- package/scripts/fake-node.js +534 -0
- package/scripts/index-bench.js +216 -0
- package/scripts/index-benchmark.js +117 -0
- package/scripts/index-build.js +40 -0
- package/scripts/live-render-check.mjs +89 -0
- package/scripts/manage-users.js +132 -0
- package/scripts/motion-check.mjs +138 -0
- package/scripts/pool-map.js +157 -0
- package/scripts/setup.js +410 -0
- package/scripts/shots.mjs +272 -0
- package/scripts/smoke.sh +327 -0
- package/scripts/ui.js +174 -0
- package/server/auth/sessions.js +221 -0
- package/server/auth/users.js +243 -0
- package/server/chain/blockfile.js +234 -0
- package/server/chain/index/build.js +193 -0
- package/server/chain/index/heights.js +36 -0
- package/server/chain/index/live.js +276 -0
- package/server/chain/index/rows.js +145 -0
- package/server/chain/index/store.js +154 -0
- package/server/chain/index/worker.js +109 -0
- package/server/chain/tx.js +310 -0
- package/server/collect/gbt.js +229 -0
- package/server/collect/logparse.js +765 -0
- package/server/collect/logtail.js +189 -0
- package/server/collect/markets.js +333 -0
- package/server/collect/mining.js +333 -0
- package/server/collect/monitor.js +2516 -0
- package/server/collect/nextblock.js +275 -0
- package/server/collect/sync.js +386 -0
- package/server/config.js +620 -0
- package/server/http/api.js +1275 -0
- package/server/http/explorer.js +418 -0
- package/server/http/server.js +412 -0
- package/server/http/sse.js +176 -0
- package/server/http/static.js +212 -0
- package/server/main.js +628 -0
- package/server/netinfo.js +253 -0
- package/server/rpc/allowlist.js +130 -0
- package/server/rpc/client.js +414 -0
- package/server/store/audit.js +148 -0
- package/server/store/history.js +220 -0
- package/server/store/ledger.js +290 -0
- package/server/store/ring.js +173 -0
- package/server/util/fmt.js +29 -0
- package/systemd/blockyard.service +100 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Server-side formatting. Deliberately small: the browser has its own copy of
|
|
2
|
+
// the display rules (public/js/fmt.js) and the two must not drift in the
|
|
3
|
+
// one place that matters -- the ETA shape, which this project already prints as
|
|
4
|
+
// DD:HH:MM:SS in its own status line.
|
|
5
|
+
|
|
6
|
+
// DD:HH:MM:SS, as used by the node's downloader ETA and its heartbeat `uptime`.
|
|
7
|
+
export function formatEta(totalSeconds) {
|
|
8
|
+
if (totalSeconds == null || !Number.isFinite(totalSeconds) || totalSeconds < 0) return null;
|
|
9
|
+
const s = Math.floor(totalSeconds);
|
|
10
|
+
const d = Math.floor(s / 86400);
|
|
11
|
+
const h = Math.floor((s % 86400) / 3600);
|
|
12
|
+
const m = Math.floor((s % 3600) / 60);
|
|
13
|
+
const sec = s % 60;
|
|
14
|
+
return `${pad(d, 2)}:${pad(h, 2)}:${pad(m, 2)}:${pad(sec, 2)}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function pad(n, w) { return String(n).padStart(w, '0'); }
|
|
18
|
+
|
|
19
|
+
// Decimal units, matching how the node prints sizes ("4.0KB" for 4096 bytes).
|
|
20
|
+
const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
|
21
|
+
export function formatBytes(n, dp = 1) {
|
|
22
|
+
if (n == null || !Number.isFinite(n)) return 'n/a';
|
|
23
|
+
let v = Math.abs(n);
|
|
24
|
+
let i = 0;
|
|
25
|
+
while (v >= 1000 && i < UNITS.length - 1) { v /= 1000; i += 1; }
|
|
26
|
+
return `${(n < 0 ? '-' : '')}${v.toFixed(i === 0 ? 0 : dp)} ${UNITS[i]}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# BlockYard -- multi-user web monitor for a Bitcoin Core node.
|
|
2
|
+
#
|
|
3
|
+
# Install:
|
|
4
|
+
# sudo cp systemd/blockyard.service /etc/systemd/system/
|
|
5
|
+
# sudo systemctl daemon-reload && sudo systemctl enable --now blockyard
|
|
6
|
+
#
|
|
7
|
+
# Read-only by design: this unit needs no access to the node's datadir beyond the
|
|
8
|
+
# log file and the RPC cookie, and the app performs no node writes unless
|
|
9
|
+
# BLOCKYARD_ENABLE_ACTIONS=1 plus an explicit BLOCKYARD_ACTIONS list are set.
|
|
10
|
+
#
|
|
11
|
+
# Nothing in this file is machine- or person-specific on purpose: it is committed,
|
|
12
|
+
# so real usernames and host addresses belong in config/local.json, which is
|
|
13
|
+
# gitignored. Two lines below are therefore placeholders you must edit.
|
|
14
|
+
[Unit]
|
|
15
|
+
Description=BlockYard - Bitcoin node monitor
|
|
16
|
+
Documentation=file:///storage/blockyard/AGENTS.md
|
|
17
|
+
After=network-online.target
|
|
18
|
+
Wants=network-online.target
|
|
19
|
+
StartLimitIntervalSec=600
|
|
20
|
+
StartLimitBurst=5
|
|
21
|
+
|
|
22
|
+
[Service]
|
|
23
|
+
Type=simple
|
|
24
|
+
# EDIT ME: the account that may read <datadir>/<chain>/.cookie and the node log.
|
|
25
|
+
# Cookie authentication is unusable without that read access, so a wrong user here
|
|
26
|
+
# shows up as a permanently-offline node rather than a clear error.
|
|
27
|
+
User=blockyard
|
|
28
|
+
Group=blockyard
|
|
29
|
+
WorkingDirectory=/storage/blockyard
|
|
30
|
+
# Name the interpreter, do not go looking for it. Measured on this box 2026-09-09:
|
|
31
|
+
# /usr/bin/node is v18.19.1 -- below package.json engines ">=22", and it starts
|
|
32
|
+
# far enough to fail on syntax, which reads like a code bug.
|
|
33
|
+
# /usr/local/bin/node is a symlink into a root-owned private runtime; that home is
|
|
34
|
+
# mode 0700, so for any User= but root it does not exist -- and
|
|
35
|
+
# /usr/local/bin is FIRST on systemd's default PATH.
|
|
36
|
+
# `/usr/bin/env node` therefore resolves either to a runtime that is too old or to
|
|
37
|
+
# nothing. Pin PATH for child processes and give ExecStart an absolute path; generate
|
|
38
|
+
# the path once with `node -v` on the target and paste it in, since this file is
|
|
39
|
+
# committed and a per-machine interpreter belongs in a drop-in, not here.
|
|
40
|
+
#Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin
|
|
41
|
+
#ExecStart=/absolute/path/to/node server/main.js
|
|
42
|
+
ExecStart=/usr/bin/env node server/main.js
|
|
43
|
+
# always, not on-failure. The outage this box actually had -- service gone, nothing on
|
|
44
|
+
# the port, no error line anywhere in the log, no journal entry because nothing was
|
|
45
|
+
# supervising it -- is exactly the case on-failure cannot see: an exit 0, or a stop that
|
|
46
|
+
# leaves no trace. With Restart=always the exit status and signal at least reach the
|
|
47
|
+
# journal, which is the difference between "it died" and "it died of 9/KILL at 08:35".
|
|
48
|
+
Restart=always
|
|
49
|
+
RestartSec=10
|
|
50
|
+
KillSignal=SIGTERM
|
|
51
|
+
# SIGTERM triggers the durable-shutdown path (history + sessions are saved with
|
|
52
|
+
# tmp+fsync+rename), so give it room to finish rather than SIGKILL mid-flush.
|
|
53
|
+
TimeoutStopSec=45
|
|
54
|
+
|
|
55
|
+
# BINDING. Which address to serve is a per-machine decision, so it lives in
|
|
56
|
+
# config/local.json (`server.hosts`), not here -- that file is gitignored and the
|
|
57
|
+
# app refuses to start if a configured address is absent at boot, rather than
|
|
58
|
+
# silently falling back to a wildcard. A previous revision of this file embedded a
|
|
59
|
+
# real LAN address here AND had two Environment= assignments concatenated onto one
|
|
60
|
+
# line, which silently discarded BLOCKYARD_PORT; both are fixed by not putting
|
|
61
|
+
# machine facts in a committed file in the first place.
|
|
62
|
+
#
|
|
63
|
+
# Consequences worth remembering: binding a single non-loopback address means
|
|
64
|
+
# 127.0.0.1 on the host itself stops working (curl checks must use that address),
|
|
65
|
+
# and clients that reach the box over a tunnel need that tunnel's address listed.
|
|
66
|
+
Environment=BLOCKYARD_PORT=21000
|
|
67
|
+
Environment=BLOCKYARD_NODE_URL=http://127.0.0.1:8331
|
|
68
|
+
Environment=BLOCKYARD_DATADIR=/home/bitcoin/.bitcoin
|
|
69
|
+
Environment=BLOCKYARD_LOGFILE=/home/bitcoin/.bitcoin/debug.log
|
|
70
|
+
Environment=BLOCKYARD_LOG_LEVEL=info
|
|
71
|
+
# ACCESS: accounts are OFF by default, so anyone who can reach the bound addresses
|
|
72
|
+
# reads this monitor (role "viewer": charts, feeds, read-only RPC console). User
|
|
73
|
+
# administration, the audit trail and node writes stay closed to them. Uncomment to
|
|
74
|
+
# require sign-in (accounts, roles, sessions, CSRF, per-user audit):
|
|
75
|
+
#Environment=BLOCKYARD_AUTH=1
|
|
76
|
+
#
|
|
77
|
+
# Node writes stay off, and while accounts are off they stay off even if actions are
|
|
78
|
+
# enabled -- a write with no identity behind it is not attributable. Enabling needs
|
|
79
|
+
# ALL of: the two lines below, accounts on (above), or the explicit
|
|
80
|
+
# BLOCKYARD_ALLOW_WRITES_WITHOUT_AUTH=1. The second line names the specific actions, so
|
|
81
|
+
# "we turned on writes" is never an unspecific statement.
|
|
82
|
+
#Environment=BLOCKYARD_ENABLE_ACTIONS=1
|
|
83
|
+
#Environment=BLOCKYARD_ACTIONS=testmempoolaccept,savemempool
|
|
84
|
+
|
|
85
|
+
# Modest hardening. NoNewPrivileges plus a read-only /home is enough here: the
|
|
86
|
+
# service must read the node's RPC cookie and log, so a full PrivateTmp/
|
|
87
|
+
# ProtectSystem=strict would fight the thing it is monitoring.
|
|
88
|
+
NoNewPrivileges=true
|
|
89
|
+
ProtectKernelTunables=true
|
|
90
|
+
ProtectKernelModules=true
|
|
91
|
+
ProtectControlGroups=true
|
|
92
|
+
RestrictSUIDSGID=true
|
|
93
|
+
LockPersonality=true
|
|
94
|
+
|
|
95
|
+
StandardOutput=journal
|
|
96
|
+
StandardError=journal
|
|
97
|
+
SyslogIdentifier=blockyard
|
|
98
|
+
|
|
99
|
+
[Install]
|
|
100
|
+
WantedBy=multi-user.target
|