ovtools 0.0.0-stage → 1.0.1

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.
Files changed (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +121 -2
  3. package/assets/common/bond-inspect.sh +368 -0
  4. package/assets/common/config.sh +263 -0
  5. package/assets/common/extract-data.sh +197 -0
  6. package/assets/common/harden-host.sh +37 -0
  7. package/assets/common/install-deps.sh +93 -0
  8. package/assets/common/node-enroll.sh +65 -0
  9. package/assets/common/node-setup.sh +150 -0
  10. package/assets/common/node-start.sh +90 -0
  11. package/assets/common/node-stop.sh +18 -0
  12. package/assets/common/node-upgrade.sh +45 -0
  13. package/assets/common/pre-run.sh +497 -0
  14. package/assets/common/promote-validator.sh +104 -0
  15. package/assets/deploy/10-prepare-host.sh +98 -0
  16. package/assets/deploy/20-install-toolchain.sh +93 -0
  17. package/assets/deploy/30-setup-node.sh +82 -0
  18. package/assets/deploy/40-start-node.sh +75 -0
  19. package/assets/deploy/50-verify.sh +259 -0
  20. package/assets/deploy/60-enroll.sh +304 -0
  21. package/assets/deploy/70-promote.sh +152 -0
  22. package/assets/deploy/lib.sh +398 -0
  23. package/assets/manage/10-bond-increase.sh +149 -0
  24. package/assets/manage/10-diagnose-node.sh +169 -0
  25. package/assets/manage/20-exit-validator.sh +259 -0
  26. package/assets/manage/25-recover-node.sh +291 -0
  27. package/assets/manage/30-status.sh +64 -0
  28. package/assets/manage/40-exit-withdraw.sh +133 -0
  29. package/assets/manage/bond_inc.sh +318 -0
  30. package/assets/manage/dashboard_monitor/app.js +1544 -0
  31. package/assets/manage/dashboard_monitor/assets/v2.2/css/base.css +113 -0
  32. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/content.css +133 -0
  33. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/controls.css +229 -0
  34. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/data.css +374 -0
  35. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/icons.css +35 -0
  36. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/motion.css +57 -0
  37. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/shell.css +51 -0
  38. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/sidebar.css +242 -0
  39. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/topbar.css +138 -0
  40. package/assets/manage/dashboard_monitor/assets/v2.2/css/fonts.css +30 -0
  41. package/assets/manage/dashboard_monitor/assets/v2.2/css/synteq-ui-v2.css +25 -0
  42. package/assets/manage/dashboard_monitor/assets/v2.2/css/theme-dark.css +38 -0
  43. package/assets/manage/dashboard_monitor/assets/v2.2/css/theme-light.css +36 -0
  44. package/assets/manage/dashboard_monitor/assets/v2.2/css/tokens.css +61 -0
  45. package/assets/manage/dashboard_monitor/assets/v2.2/fonts/GoogleSansCode-Medium.ttf +0 -0
  46. package/assets/manage/dashboard_monitor/assets/v2.2/fonts/GoogleSansCode-Regular.ttf +0 -0
  47. package/assets/manage/dashboard_monitor/assets/v2.2/fonts/GoogleSansCode-SemiBold.ttf +0 -0
  48. package/assets/manage/dashboard_monitor/assets/v2.2/js/synteq-ui-v2.js +869 -0
  49. package/assets/manage/dashboard_monitor/deploy-dashboard.sh +230 -0
  50. package/assets/manage/dashboard_monitor/favicon.svg +13 -0
  51. package/assets/manage/dashboard_monitor/index.html +1197 -0
  52. package/assets/manage/dashboard_monitor/nginx-octra.conf +76 -0
  53. package/assets/manage/dashboard_monitor/octra-dashboard.service +29 -0
  54. package/assets/manage/dashboard_monitor/octra-node-prune.cron +12 -0
  55. package/assets/manage/dashboard_monitor/octra-node-prune.service +16 -0
  56. package/assets/manage/dashboard_monitor/octra-node-prune.timer +12 -0
  57. package/assets/manage/dashboard_monitor/prune-node-junk.sh +329 -0
  58. package/assets/manage/dashboard_monitor/server.py +1887 -0
  59. package/assets/manage/dashboard_monitor/ssl-certbot.sh +90 -0
  60. package/assets/manage/dashboard_monitor/styles.css +327 -0
  61. package/assets/manage/lib.sh +347 -0
  62. package/assets/manifest.json +143 -0
  63. package/assets/migrate/00-backup-identity.sh +67 -0
  64. package/assets/migrate/01-prepare-target.sh +145 -0
  65. package/assets/migrate/02-authorize-pull.sh +43 -0
  66. package/assets/migrate/03-pull-state.sh +102 -0
  67. package/assets/migrate/04-stop-source.sh +85 -0
  68. package/assets/migrate/05-finalize-target.sh +140 -0
  69. package/assets/migrate/06-start-target.sh +57 -0
  70. package/assets/migrate/07-verify.sh +237 -0
  71. package/assets/migrate/08-rollback.sh +54 -0
  72. package/assets/migrate/lib.sh +149 -0
  73. package/assets/upgrade/10-preflight.sh +120 -0
  74. package/assets/upgrade/20-upgrade.sh +142 -0
  75. package/assets/upgrade/30-manual-upgrade.sh +129 -0
  76. package/assets/upgrade/40-storage-prune.sh +65 -0
  77. package/assets/upgrade/50-status.sh +58 -0
  78. package/assets/upgrade/lib.sh +232 -0
  79. package/bin/ovtools.js +32 -0
  80. package/dist/api/checks.d.ts +6 -0
  81. package/dist/api/checks.d.ts.map +1 -0
  82. package/dist/api/checks.js +173 -0
  83. package/dist/api/checks.js.map +1 -0
  84. package/dist/api/hostkeys.d.ts +10 -0
  85. package/dist/api/hostkeys.d.ts.map +1 -0
  86. package/dist/api/hostkeys.js +58 -0
  87. package/dist/api/hostkeys.js.map +1 -0
  88. package/dist/api/jobs.d.ts +33 -0
  89. package/dist/api/jobs.d.ts.map +1 -0
  90. package/dist/api/jobs.js +486 -0
  91. package/dist/api/jobs.js.map +1 -0
  92. package/dist/api/nodes.d.ts +16 -0
  93. package/dist/api/nodes.d.ts.map +1 -0
  94. package/dist/api/nodes.js +126 -0
  95. package/dist/api/nodes.js.map +1 -0
  96. package/dist/api/server.d.ts +3 -0
  97. package/dist/api/server.d.ts.map +1 -0
  98. package/dist/api/server.js +443 -0
  99. package/dist/api/server.js.map +1 -0
  100. package/dist/cli.d.ts +3 -0
  101. package/dist/cli.d.ts.map +1 -0
  102. package/dist/cli.js +301 -0
  103. package/dist/cli.js.map +1 -0
  104. package/dist/constants.d.ts +76 -0
  105. package/dist/constants.d.ts.map +1 -0
  106. package/dist/constants.js +150 -0
  107. package/dist/constants.js.map +1 -0
  108. package/dist/index.d.ts +18 -0
  109. package/dist/index.d.ts.map +1 -0
  110. package/dist/index.js +60 -0
  111. package/dist/index.js.map +1 -0
  112. package/dist/orchestrator/base.d.ts +52 -0
  113. package/dist/orchestrator/base.d.ts.map +1 -0
  114. package/dist/orchestrator/base.js +219 -0
  115. package/dist/orchestrator/base.js.map +1 -0
  116. package/dist/orchestrator/deploy.d.ts +33 -0
  117. package/dist/orchestrator/deploy.d.ts.map +1 -0
  118. package/dist/orchestrator/deploy.js +313 -0
  119. package/dist/orchestrator/deploy.js.map +1 -0
  120. package/dist/orchestrator/manage.d.ts +28 -0
  121. package/dist/orchestrator/manage.d.ts.map +1 -0
  122. package/dist/orchestrator/manage.js +267 -0
  123. package/dist/orchestrator/manage.js.map +1 -0
  124. package/dist/orchestrator/migrate.d.ts +31 -0
  125. package/dist/orchestrator/migrate.d.ts.map +1 -0
  126. package/dist/orchestrator/migrate.js +442 -0
  127. package/dist/orchestrator/migrate.js.map +1 -0
  128. package/dist/ssh/client.d.ts +39 -0
  129. package/dist/ssh/client.d.ts.map +1 -0
  130. package/dist/ssh/client.js +418 -0
  131. package/dist/ssh/client.js.map +1 -0
  132. package/dist/test/core.test.d.ts +2 -0
  133. package/dist/test/core.test.d.ts.map +1 -0
  134. package/dist/test/core.test.js +188 -0
  135. package/dist/test/core.test.js.map +1 -0
  136. package/dist/types.d.ts +267 -0
  137. package/dist/types.d.ts.map +1 -0
  138. package/dist/types.js +3 -0
  139. package/dist/types.js.map +1 -0
  140. package/dist/utils/assets.d.ts +28 -0
  141. package/dist/utils/assets.d.ts.map +1 -0
  142. package/dist/utils/assets.js +583 -0
  143. package/dist/utils/assets.js.map +1 -0
  144. package/dist/utils/browser.d.ts +2 -0
  145. package/dist/utils/browser.d.ts.map +1 -0
  146. package/dist/utils/browser.js +23 -0
  147. package/dist/utils/browser.js.map +1 -0
  148. package/dist/utils/dashboard.d.ts +16 -0
  149. package/dist/utils/dashboard.d.ts.map +1 -0
  150. package/dist/utils/dashboard.js +177 -0
  151. package/dist/utils/dashboard.js.map +1 -0
  152. package/dist/utils/helpers.d.ts +29 -0
  153. package/dist/utils/helpers.d.ts.map +1 -0
  154. package/dist/utils/helpers.js +204 -0
  155. package/dist/utils/helpers.js.map +1 -0
  156. package/dist/utils/scripts.d.ts +60 -0
  157. package/dist/utils/scripts.d.ts.map +1 -0
  158. package/dist/utils/scripts.js +174 -0
  159. package/dist/utils/scripts.js.map +1 -0
  160. package/dist/utils/state.d.ts +12 -0
  161. package/dist/utils/state.d.ts.map +1 -0
  162. package/dist/utils/state.js +44 -0
  163. package/dist/utils/state.js.map +1 -0
  164. package/dist/utils/tar.d.ts +11 -0
  165. package/dist/utils/tar.d.ts.map +1 -0
  166. package/dist/utils/tar.js +93 -0
  167. package/dist/utils/tar.js.map +1 -0
  168. package/dist/utils/update.d.ts +9 -0
  169. package/dist/utils/update.d.ts.map +1 -0
  170. package/dist/utils/update.js +134 -0
  171. package/dist/utils/update.js.map +1 -0
  172. package/dist/utils/websocket.d.ts +10 -0
  173. package/dist/utils/websocket.d.ts.map +1 -0
  174. package/dist/utils/websocket.js +203 -0
  175. package/dist/utils/websocket.js.map +1 -0
  176. package/package.json +55 -4
  177. package/public/app.js +2736 -0
  178. package/public/assets/v2.2/css/base.css +113 -0
  179. package/public/assets/v2.2/css/components/content.css +133 -0
  180. package/public/assets/v2.2/css/components/controls.css +229 -0
  181. package/public/assets/v2.2/css/components/data.css +373 -0
  182. package/public/assets/v2.2/css/components/icons.css +35 -0
  183. package/public/assets/v2.2/css/components/motion.css +57 -0
  184. package/public/assets/v2.2/css/components/shell.css +51 -0
  185. package/public/assets/v2.2/css/components/sidebar.css +242 -0
  186. package/public/assets/v2.2/css/components/topbar.css +138 -0
  187. package/public/assets/v2.2/css/fonts.css +30 -0
  188. package/public/assets/v2.2/css/synteq-ui-v2.css +25 -0
  189. package/public/assets/v2.2/css/theme-dark.css +38 -0
  190. package/public/assets/v2.2/css/theme-light.css +36 -0
  191. package/public/assets/v2.2/css/tokens.css +61 -0
  192. package/public/assets/v2.2/fonts/GoogleSansCode-Medium.ttf +0 -0
  193. package/public/assets/v2.2/fonts/GoogleSansCode-Regular.ttf +0 -0
  194. package/public/assets/v2.2/fonts/GoogleSansCode-SemiBold.ttf +0 -0
  195. package/public/assets/v2.2/js/synteq-ui-v2.js +869 -0
  196. package/public/favicon.svg +13 -0
  197. package/public/index.html +1083 -0
  198. package/public/styles.css +580 -0
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env bash
2
+ # ===================================================================
3
+ # 20-upgrade.sh - update the node with the OFFICIAL tool
4
+ #
5
+ # The upstream README ("How to update (if you are already a validator)") names one
6
+ # command that monitors the repo, checks the packages, builds a fresh binary,
7
+ # restarts the node and waits until it is guaranteed to be operational:
8
+ #
9
+ # sh controls/upgrade.sh # test the mechanics, changes nothing
10
+ # sh controls/upgrade.sh --apply # do it
11
+ #
12
+ # This step runs the test first (the README recommends checking first), then the
13
+ # apply, and reads the verdict from what the tool prints:
14
+ #
15
+ # validator_active | observer_synced -> the node is online, the binary is the
16
+ # one just built, the head is caught up
17
+ # pending -> do NOT restart, the chain/build is not
18
+ # ready yet: soft stop, re-run later
19
+ # refused -> the reason is in the output (FAILED)
20
+ #
21
+ # It NEVER runs `--sync`, never touches config/network.env and never re-enrolls.
22
+ #
23
+ # Usage: sudo bash 20-upgrade.sh
24
+ # Env: UPGRADE_APPLY (1) - 0 = only the test run
25
+ # UPGRADE_WAIT_SECONDS (900) - passed to --wait-seconds
26
+ # UPGRADE_EXTRA - extra flags for the tool, e.g.
27
+ # "--public-commit <sha> --source-commit <sha>", or
28
+ # "--unit octra-node.service" / "--user-unit"
29
+ # UPGRADE_TEST_TIMEOUT (1800) / UPGRADE_TIMEOUT (5400)
30
+ # ===================================================================
31
+
32
+ set -euo pipefail
33
+ source "$(dirname "$0")/lib.sh"
34
+
35
+ require_root
36
+ set_status RUNNING "upgrade"
37
+
38
+ APPLY="${UPGRADE_APPLY:-1}"
39
+ WAIT="${UPGRADE_WAIT_SECONDS:-900}"
40
+ EXTRA="${UPGRADE_EXTRA:-}"
41
+ TOOL_OUT="${UPGRADE_DIR}/upgrade-tool.out"
42
+
43
+ [[ -f "${UPGRADE_SH}" ]] || die "controls/upgrade.sh is missing on this node - use the manual update (fallback phase)"
44
+
45
+ ensure_tool git git || die "git is missing and could not be installed"
46
+ read_state
47
+ [[ "${PROCESS}" == "online" || -z "${PROCESS}" ]] || warn "the node process is ${PROCESS} - the tool will start/restart it"
48
+
49
+ BEFORE_COMMIT=$(source_commit)
50
+ BEFORE_HEAD=$(git_head)
51
+ log "=== update with the official tool: controls/upgrade.sh${EXTRA:+ ${EXTRA}} --wait-seconds ${WAIT} ==="
52
+ log "before : SOURCE_COMMIT=${BEFORE_COMMIT:-unknown} git HEAD=${BEFORE_HEAD:-unknown} role=${ROLE:-?} rpc=${RPC:-?}"
53
+ log "repository: $(git_remote)"
54
+ log "the node is NOT re-synced and NOT re-enrolled (upstream rule)"
55
+
56
+ : > "${TOOL_OUT}"
57
+
58
+ run_tool() { # run_tool <timeout> <command...> -> streams into the console + the log, returns the tool's rc
59
+ local limit="$1" rc=0
60
+ shift
61
+ set +e
62
+ timeout "${limit}" su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && $*" 2>&1 \
63
+ | tee -a "${TOOL_OUT}" | sed 's/^/ /'
64
+ rc=${PIPESTATUS[0]}
65
+ set -e
66
+ return "${rc}"
67
+ }
68
+
69
+ # --- 1. the test run (changes nothing) ---------------------------------
70
+ log "--- test run: sh controls/upgrade.sh (nothing is rebuilt or restarted) ---"
71
+ TEST_RC=0
72
+ run_tool "${UPGRADE_TEST_TIMEOUT:-1800}" "sh controls/upgrade.sh" || TEST_RC=$?
73
+ TEST_VERDICT=$(upgrade_verdict "${TOOL_OUT}")
74
+ if (( TEST_RC != 0 )); then
75
+ REASON=$(upgrade_reason "${TOOL_OUT}")
76
+ if [[ "${TEST_VERDICT}" == "pending" ]]; then
77
+ warn "the tool reports 'pending'${REASON:+ - ${REASON}}"
78
+ warn "do NOT restart the node manually: re-run this phase once the tool can finish"
79
+ set_status WAITING-UPGRADE "the test run is pending${REASON:+ - ${REASON}} - re-run the update later"
80
+ exit 2
81
+ fi
82
+ die "the test run refused (exit ${TEST_RC})${REASON:+: ${REASON}} - nothing was changed; see the output above"
83
+ fi
84
+ log "the test run passed${TEST_VERDICT:+ (${TEST_VERDICT})}"
85
+
86
+ if [[ "${APPLY}" != "1" ]]; then
87
+ log "UPGRADE_APPLY=0: test only - the node is untouched"
88
+ set_status DONE "test-only (SOURCE_COMMIT=${BEFORE_COMMIT:-unknown})"
89
+ exit 0
90
+ fi
91
+
92
+ # --- 2. apply -----------------------------------------------------------
93
+ # shellcheck disable=SC2086
94
+ ARGS="--apply --wait-seconds ${WAIT} ${EXTRA}"
95
+ log "--- apply: sh controls/upgrade.sh ${ARGS} (pull + build + restart + wait) ---"
96
+ APPLY_RC=0
97
+ run_tool "${UPGRADE_TIMEOUT:-5400}" "sh controls/upgrade.sh ${ARGS}" || APPLY_RC=$?
98
+ VERDICT=$(upgrade_verdict "${TOOL_OUT}")
99
+ REASON=$(upgrade_reason "${TOOL_OUT}")
100
+
101
+ case "${VERDICT}" in
102
+ pending)
103
+ warn "the tool reports 'pending'${REASON:+ - ${REASON}}"
104
+ warn "do NOT restart the node manually (upstream) - re-run this phase later"
105
+ set_status WAITING-UPGRADE "status pending${REASON:+ - ${REASON}} - re-run the update later"
106
+ exit 2
107
+ ;;
108
+ refused)
109
+ die "the tool refused the update${REASON:+: ${REASON}} - see the output above"
110
+ ;;
111
+ esac
112
+
113
+ # --- 3. verify what is running now -------------------------------------
114
+ AFTER_COMMIT=$(source_commit)
115
+ AFTER_HEAD=$(git_head)
116
+ read_state
117
+ log "after : SOURCE_COMMIT=${AFTER_COMMIT:-unknown} git HEAD=${AFTER_HEAD:-unknown} role=${ROLE:-?} process=${PROCESS:-?} rpc=${RPC:-?} voting=${VOTING:-?} epoch=${EPOCH:-?}"
118
+ log "binary : ${BINARY:-unknown}${PVAC:+ pvac ${PVAC}}"
119
+
120
+ if [[ "${PROCESS}" != "online" || "${RPC}" != "ready" ]]; then
121
+ warn "the node is not back yet (process=${PROCESS:-?} rpc=${RPC:-?})"
122
+ warn "check it with: su - ${NODE_USER} -c 'cd ${NODE_SRC_DIR} && sh controls/stat.sh --logs'"
123
+ set_status WAITING-UPGRADE "the update ran but the node is not ready yet (process=${PROCESS:-?} rpc=${RPC:-?}) - re-run the update or read stat.sh --logs"
124
+ exit 2
125
+ fi
126
+
127
+ if (( APPLY_RC != 0 )); then
128
+ warn "the tool exited ${APPLY_RC} but the node is online as ${ROLE:-?}${VERDICT:+ (verdict ${VERDICT})}"
129
+ fi
130
+ if [[ -n "${AFTER_COMMIT}" && -n "${AFTER_HEAD}" && "${AFTER_COMMIT}" != "${AFTER_HEAD}" ]]; then
131
+ warn "SOURCE_COMMIT (${AFTER_COMMIT}) does not match git HEAD (${AFTER_HEAD}) - check the checkout"
132
+ fi
133
+
134
+ if [[ -z "${VERDICT}" ]]; then
135
+ if [[ "${ACTIVE}" == "true" ]]; then VERDICT="validator_active"; else VERDICT="observer_synced"; fi
136
+ fi
137
+ if [[ "${ACTIVE}" == "true" ]]; then
138
+ log "=== the node is an ACTIVE validator again, running the binary it just built ==="
139
+ else
140
+ log "=== the node is online and synced (observer) with the freshly built binary ==="
141
+ fi
142
+ set_status DONE "verdict=${VERDICT} commit=${AFTER_HEAD:-unknown} role=${ROLE:-?} active=${ACTIVE:-?} epoch=${EPOCH:-?}"
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env bash
2
+ # ===================================================================
3
+ # 30-manual-upgrade.sh - the documented MANUAL update (fallback)
4
+ #
5
+ # Upstream README, "Manual update (when the tool cannot run)":
6
+ #
7
+ # sudo -iu octra
8
+ # cd /opt/octra/libv_litecore
9
+ # git pull --ff-only
10
+ # cat SOURCE_COMMIT
11
+ # sh controls/check.sh
12
+ # SWITCH="$PWD/runtime_data/toolchains/ocaml"
13
+ # make -C mcl MCL_FP_BIT=256 MCL_FR_BIT=256 lib/libmcl.a
14
+ # opam exec --switch "$SWITCH" -- dune build --profile release \
15
+ # bin/octra_node.exe bin/octra_pvac_worker.exe \
16
+ # bin/octra_state_sync_client.exe bin/octra_state_sync_manifest.exe \
17
+ # bin/bft_control_tx.exe
18
+ # sh controls/stop.sh
19
+ # sh controls/run.sh --rebind-runtime
20
+ # sh controls/stat.sh
21
+ #
22
+ # Every command runs as the node user from the node directory (the checkout and
23
+ # the opam switch belong to it). This step NEVER runs `--sync`, never edits
24
+ # config/network.env and never re-enrolls - the node keeps its identity and its
25
+ # data, only the binary is replaced and the process restarted.
26
+ #
27
+ # Usage: sudo bash 30-manual-upgrade.sh
28
+ # Env: MANUAL_APPLY (1) - 0 = pull + check + build only (no stop/run)
29
+ # PULL_TIMEOUT (600) / CHECK_TIMEOUT (300) / MAKE_TIMEOUT (1800)
30
+ # BUILD_TIMEOUT (5400) / STOP_TIMEOUT (180) / RUN_TIMEOUT (900)
31
+ # ===================================================================
32
+
33
+ set -euo pipefail
34
+ source "$(dirname "$0")/lib.sh"
35
+
36
+ require_root
37
+ set_status RUNNING "manual-upgrade"
38
+
39
+ APPLY="${MANUAL_APPLY:-1}"
40
+ BUILD_LOG="${UPGRADE_DIR}/manual-build.out"
41
+
42
+ [[ -d "${NODE_SRC_DIR}/.git" ]] || die "${NODE_SRC_DIR} is not a git checkout - cannot pull"
43
+ [[ -f "${NODE_ENV}" ]] || die "node.env is missing (${NODE_ENV}) - this is not the node host"
44
+
45
+ ensure_build_tools
46
+
47
+ # the opam switch the toolchain step built (upstream: $PWD/runtime_data/toolchains/ocaml)
48
+ SWITCH="$(ocaml_switch_root 2>/dev/null || printf '%s' "${NODE_SRC_DIR}/runtime_data/toolchains/ocaml")"
49
+ [[ -d "${SWITCH}/_opam/.opam-switch" ]] || die "the opam switch is not built (${SWITCH}/_opam/.opam-switch missing) - run the toolchain step (scripts/deploy/20-install-toolchain.sh) first"
50
+
51
+ BEFORE_COMMIT=$(source_commit)
52
+ BEFORE_HEAD=$(git_head)
53
+ log "=== manual update on $(hostname) ==="
54
+ log "before : SOURCE_COMMIT=${BEFORE_COMMIT:-unknown} git HEAD=${BEFORE_HEAD:-unknown}"
55
+ log "opam switch: ${SWITCH}"
56
+ log "the node is NOT re-synced and NOT re-enrolled (upstream rule)"
57
+
58
+ run_as_node() { # run_as_node <timeout> <label> <command...>
59
+ local limit="$1" label="$2" rc=0
60
+ shift 2
61
+ log "--- ${label} ---"
62
+ set +e
63
+ timeout "${limit}" su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && $*" 2>&1 \
64
+ | tee -a "${BUILD_LOG}" | sed 's/^/ /'
65
+ rc=${PIPESTATUS[0]}
66
+ set -e
67
+ return "${rc}"
68
+ }
69
+
70
+ : > "${BUILD_LOG}"
71
+
72
+
73
+ # --- 1. pull + verify --------------------------------------------------
74
+ run_as_node "${PULL_TIMEOUT:-600}" "git pull --ff-only" "git pull --ff-only" \
75
+ || die "git pull failed - see the output above (a dirty tree or a diverged branch stops here)"
76
+
77
+ AFTER_COMMIT=$(source_commit)
78
+ AFTER_HEAD=$(git_head)
79
+ log "after the pull: SOURCE_COMMIT=${AFTER_COMMIT:-unknown} git HEAD=${AFTER_HEAD:-unknown}"
80
+
81
+ if [[ -f "${CHECK_SH}" ]]; then
82
+ run_as_node "${CHECK_TIMEOUT:-300}" "controls/check.sh (verify the package)" "sh controls/check.sh" \
83
+ || die "controls/check.sh reported a problem - fix it before building"
84
+ else
85
+ warn "controls/check.sh is missing - skipping the package verification"
86
+ fi
87
+
88
+ # --- 2. build ----------------------------------------------------------
89
+ run_as_node "${MAKE_TIMEOUT:-1800}" "make -C mcl (MCL_FP_BIT=256 MCL_FR_BIT=256)" \
90
+ "make -C mcl MCL_FP_BIT=256 MCL_FR_BIT=256 lib/libmcl.a" \
91
+ || die "the mcl library did not build - see the output above"
92
+
93
+ run_as_node "${BUILD_TIMEOUT:-5400}" "dune build --profile release (node + pvac + sync + bft)" \
94
+ "opam exec --switch '${SWITCH}' -- dune build --profile release bin/octra_node.exe bin/octra_pvac_worker.exe bin/octra_state_sync_client.exe bin/octra_state_sync_manifest.exe bin/bft_control_tx.exe" \
95
+ || die "the dune build failed - see the output above (the running node is untouched so far)"
96
+
97
+ log "the build finished - the node is still running the old binary"
98
+
99
+ if [[ "${APPLY}" != "1" ]]; then
100
+ log "MANUAL_APPLY=0: build only - the node was not restarted"
101
+ set_status DONE "build-only commit=${AFTER_HEAD:-unknown} (node still on the old binary)"
102
+ exit 0
103
+ fi
104
+
105
+ # --- 3. restart on the fresh binary ------------------------------------
106
+ run_as_node "${STOP_TIMEOUT:-180}" "controls/stop.sh" "sh controls/stop.sh" \
107
+ || die "controls/stop.sh failed - the node may still be running; check it before retrying"
108
+
109
+ run_as_node "${RUN_TIMEOUT:-900}" "controls/run.sh --rebind-runtime" "sh controls/run.sh --rebind-runtime" \
110
+ || warn "controls/run.sh reported an error - checking the node state anyway"
111
+
112
+ read_state
113
+ log "node after the restart: role=${ROLE:-?} process=${PROCESS:-?} rpc=${RPC:-?} voting=${VOTING:-?} epoch=${EPOCH:-?}"
114
+ log "binary : ${BINARY:-unknown}${PVAC:+ pvac ${PVAC}}"
115
+
116
+ if [[ "${PROCESS}" != "online" ]]; then
117
+ warn "the node process is ${PROCESS:-unknown} - the restart did not come up"
118
+ warn "read the log: su - ${NODE_USER} -c 'cd ${NODE_SRC_DIR} && sh controls/stat.sh --logs'"
119
+ set_status WAITING-UPGRADE "the manual build finished but the node is ${PROCESS:-unknown} - check stat.sh --logs"
120
+ exit 2
121
+ fi
122
+ if [[ "${RPC}" != "ready" ]]; then
123
+ warn "the node is online but its rpc is ${RPC:-unknown} - it is probably replaying; re-run to re-check"
124
+ set_status WAITING-RPC "the node is online again but rpc=${RPC:-unknown} - re-run the manual update to re-check"
125
+ exit 2
126
+ fi
127
+
128
+ log "=== the node is back on the freshly built binary ==="
129
+ set_status DONE "manual-upgrade commit=${AFTER_HEAD:-unknown} role=${ROLE:-?} active=${ACTIVE:-?} epoch=${EPOCH:-?}"
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env bash
2
+ # ===================================================================
3
+ # 40-storage-prune.sh - "Remove preserved states" (upstream README)
4
+ #
5
+ # sh controls/storage.sh # report
6
+ # sh controls/storage.sh --prune-prior --yes # drop the previous states
7
+ # sh controls/storage.sh # report again
8
+ #
9
+ # A node keeps the states of the previous epochs ("prior"/preserved states) so it
10
+ # can serve peers that lag behind; they grow until the store is oversized. The
11
+ # documented maintenance is to drop them from time to time - which is also what
12
+ # the daily prune job on this host now does (dashboard/prune-node-junk.sh).
13
+ #
14
+ # Read-only when PRUNE_APPLY=0. Nothing else on the node is touched: no sync, no
15
+ # re-enroll, the node keeps running.
16
+ #
17
+ # Usage: sudo bash 40-storage-prune.sh
18
+ # Env: PRUNE_APPLY (1) - 0 = report only
19
+ # PRUNE_TIMEOUT (900) / STORAGE_TIMEOUT (180)
20
+ # ===================================================================
21
+
22
+ set -euo pipefail
23
+ source "$(dirname "$0")/lib.sh"
24
+
25
+ require_root
26
+ set_status RUNNING "storage-prune"
27
+
28
+ APPLY="${PRUNE_APPLY:-1}"
29
+ [[ -f "${STORAGE_SH}" ]] || die "controls/storage.sh is missing on this node - update the node first (the tool does not exist on this version)"
30
+
31
+ log "=== preserved states on $(hostname) ==="
32
+ log "--- storage before ---"
33
+ BEFORE=$(storage_report)
34
+ printf '%s\n' "${BEFORE}" | sed 's/^/ /'
35
+ BEFORE_LINE=$(printf '%s\n' "${BEFORE}" | grep -iE 'preserved|reclaim|prior' | tail -1 || true)
36
+
37
+ if [[ "${APPLY}" != "1" ]]; then
38
+ log "PRUNE_APPLY=0: report only - nothing was pruned"
39
+ set_status DONE "report-only${BEFORE_LINE:+ - ${BEFORE_LINE}}"
40
+ exit 0
41
+ fi
42
+
43
+ read_state
44
+ log "node while pruning: process=${PROCESS:-?} rpc=${RPC:-?} role=${ROLE:-?} epoch=${EPOCH:-?}"
45
+
46
+ log "--- storage.sh --prune-prior --yes ---"
47
+ RC=0
48
+ OUT=$(prune_states) || RC=$?
49
+ printf '%s\n' "${OUT}" | sed 's/^/ /'
50
+ if (( RC != 0 )); then
51
+ REASON=$(printf '%s\n' "${OUT}" | grep -aiE 'error|refus|denied|not |missing|failed' | tail -1 || true)
52
+ die "controls/storage.sh --prune-prior refused (exit ${RC})${REASON:+: ${REASON}}"
53
+ fi
54
+
55
+ log "--- storage after ---"
56
+ AFTER=$(storage_report)
57
+ printf '%s\n' "${AFTER}" | sed 's/^/ /'
58
+ AFTER_LINE=$(printf '%s\n' "${AFTER}" | grep -iE 'preserved|reclaim|prior' | tail -1 || true)
59
+
60
+ read_state
61
+ log "node after pruning: process=${PROCESS:-?} rpc=${RPC:-?} role=${ROLE:-?} epoch=${EPOCH:-?}"
62
+ [[ "${PROCESS}" == "online" ]] || warn "the node process is ${PROCESS:-unknown} - check it with stat.sh --logs"
63
+
64
+ log "=== preserved states pruned ==="
65
+ set_status DONE "${AFTER_LINE:-pruned}${BEFORE_LINE:+ (before: ${BEFORE_LINE})}"
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env bash
2
+ # ===================================================================
3
+ # 50-status.sh - versions + storage of the running node (read-only)
4
+ #
5
+ # Prints what the console shows for the update program: the commit the checkout
6
+ # says it is (SOURCE_COMMIT), the git HEAD/branch (and whether the tree is dirty),
7
+ # the hashes of the BINARY that is actually running (stat.sh) and the storage
8
+ # report of the node's own tool. Nothing is pulled, built or restarted.
9
+ #
10
+ # Usage: sudo bash 50-status.sh
11
+ # ===================================================================
12
+
13
+ set -euo pipefail
14
+ source "$(dirname "$0")/lib.sh"
15
+
16
+ require_root
17
+ set_status RUNNING "status"
18
+
19
+ ensure_tool git git || die "git is missing and could not be installed"
20
+ ensure_tool jq jq || warn "jq is missing - the wallet address cannot be read"
21
+
22
+ COMMIT=$(source_commit)
23
+ HEAD=$(git_head)
24
+ BRANCH=$(git_branch)
25
+ DIRTY=$(git_dirty)
26
+ REMOTE=$(git_remote)
27
+ read_state
28
+ ADDR=$(wallet_address || echo unknown)
29
+
30
+ log "=== update status: $(hostname) ==="
31
+ log "wallet : ${ADDR}"
32
+ log "repository: ${REMOTE}"
33
+ log "checkout : SOURCE_COMMIT=${COMMIT:-unknown} git HEAD=${HEAD:-unknown}${BRANCH:+ on ${BRANCH}}${DIRTY:+ (dirty working tree)}"
34
+ if [[ -n "${COMMIT}" && -n "${HEAD}" && "${COMMIT}" != "${HEAD}" ]]; then
35
+ log " SOURCE_COMMIT and git HEAD differ - the checkout was rebuilt from another commit"
36
+ fi
37
+ log "running : role=${ROLE:-?} process=${PROCESS:-?} rpc=${RPC:-?} voting=${VOTING:-?} epoch=${EPOCH:-?} uptime=${PROCESS_UP:-?}"
38
+ log "binary : ${BINARY:-unknown}"
39
+ log "pvac : ${PVAC:-unknown}"
40
+ log "membership: active=${ACTIVE:-?} scheduled=${SCHED:-?} enrollment=${ENROLL:-?}"
41
+
42
+ if [[ -f "${STORAGE_SH}" ]]; then
43
+ log "--- controls/storage.sh ---"
44
+ STORE=$(storage_report)
45
+ printf '%s\n' "${STORE}" | sed 's/^/ /'
46
+ STORAGE_LINE=$(storage_fields)
47
+ else
48
+ warn "controls/storage.sh is missing - this node version has no storage tool"
49
+ STORAGE_LINE=""
50
+ fi
51
+
52
+ if [[ -f "${UPGRADE_SH}" ]]; then
53
+ log "official tool: controls/upgrade.sh present (sh controls/upgrade.sh / --apply)"
54
+ else
55
+ warn "controls/upgrade.sh is missing - use the manual update (fallback)"
56
+ fi
57
+
58
+ set_status DONE "commit=${HEAD:-unknown}${BRANCH:+ on ${BRANCH}} role=${ROLE:-?} active=${ACTIVE:-?}${STORAGE_LINE:+ - ${STORAGE_LINE}}"
@@ -0,0 +1,232 @@
1
+ #!/usr/bin/env bash
2
+ # ===================================================================
3
+ # scripts/upgrade/lib.sh - shared helpers for the UPDATE-NODE actions
4
+ #
5
+ # The update actions of the console's "Manage active node" block (they are not a
6
+ # tab of their own since 2026-11-05): they do not create, move or operate the
7
+ # validator - they UPDATE the node that is already running, exactly as the
8
+ # upstream README describes ("How to update (if you are already a validator)"):
9
+ #
10
+ # * the official tool: controls/upgrade.sh (test, changes nothing)
11
+ # controls/upgrade.sh --apply (pull, build, restart,
12
+ # wait, verify)
13
+ # * the manual fallback: git pull --ff-only -> controls/check.sh -> make -C mcl
14
+ # -> dune build -> controls/stop.sh -> controls/run.sh
15
+ # --rebind-runtime -> controls/stat.sh
16
+ # * housekeeping: controls/storage.sh [--prune-prior --yes]
17
+ # ("Remove preserved states")
18
+ #
19
+ # NEVER (upstream, in capitals): do not run `--sync` again, do not change
20
+ # config/network.env, do not re-enroll the node. Every step here only pulls,
21
+ # builds, restarts and reads.
22
+ #
23
+ # /root/upgrade/ this program (/root/deploy, /root/migration, /root/manage)
24
+ # ===================================================================
25
+ set -euo pipefail
26
+
27
+ # Tool policy (check -> install -> continue) lives in scripts/config.sh, which is
28
+ # pushed to /root/config.sh next to these scripts.
29
+ CONFIG_FILE="${CONFIG_FILE:-/root/config.sh}"
30
+ if [[ -f "${CONFIG_FILE}" ]]; then
31
+ # shellcheck disable=SC1090
32
+ source "${CONFIG_FILE}"
33
+ fi
34
+ if ! declare -F ensure_tool >/dev/null 2>&1; then
35
+ ensure_tool() { command -v "$1" >/dev/null 2>&1 || die "tool $1 is missing and ${CONFIG_FILE} cannot install it (push the scripts again)"; }
36
+ fi
37
+
38
+ UPGRADE_DIR="${UPGRADE_DIR:-/root/upgrade}"
39
+ UPGRADE_LOG="${UPGRADE_LOG:-${UPGRADE_DIR}/upgrade.log}"
40
+ UPGRADE_STATUS="${UPGRADE_STATUS:-${UPGRADE_DIR}/status}"
41
+
42
+ NODE_SRC_DIR="${NODE_SRC_DIR:-/opt/octra/libv_litecore}"
43
+ NODE_DATA_ROOT="${NODE_DATA_ROOT:-/var/lib/octra}"
44
+ NODE_DATA_DIR="${NODE_DATA_DIR:-${NODE_DATA_ROOT}/devnet}"
45
+ NODE_WALLET="${NODE_WALLET:-${NODE_SRC_DIR}/.keys/validator/wallet.json}"
46
+ NODE_ENV="${NODE_ENV:-${NODE_SRC_DIR}/.keys/validator/node.env}"
47
+ NODE_USER="${NODE_USER:-octra}"
48
+ NODE_LOG="${NODE_LOG:-${NODE_SRC_DIR}/data/operator_logs/node.log}"
49
+ # the control scripts the upstream README names
50
+ UPGRADE_SH="${UPGRADE_SH:-${NODE_SRC_DIR}/controls/upgrade.sh}"
51
+ STORAGE_SH="${STORAGE_SH:-${NODE_SRC_DIR}/controls/storage.sh}"
52
+ CHECK_SH="${CHECK_SH:-${NODE_SRC_DIR}/controls/check.sh}"
53
+ STOP_SH="${STOP_SH:-${NODE_SRC_DIR}/controls/stop.sh}"
54
+ RUN_SH="${RUN_SH:-${NODE_SRC_DIR}/controls/run.sh}"
55
+ # where SOURCE_COMMIT lives in the checkout (upstream ships it)
56
+ SOURCE_COMMIT_FILE="${SOURCE_COMMIT_FILE:-${NODE_SRC_DIR}/SOURCE_COMMIT}"
57
+
58
+ mkdir -p "${UPGRADE_DIR}"
59
+
60
+ log() { echo -e "[upgrade] $*" | tee -a "${UPGRADE_LOG}"; }
61
+ warn() { echo -e "[warn] $*" | tee -a "${UPGRADE_LOG}" >&2; }
62
+ err() { echo -e "[err] $*" | tee -a "${UPGRADE_LOG}" >&2; }
63
+
64
+ set_status() { # set_status <STATE> [detail...] - read by the Windows console
65
+ local state="$1" detail
66
+ shift || true
67
+ detail="$*"
68
+ printf '%s %s %s\n' "${state}" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "${detail}" > "${UPGRADE_STATUS}"
69
+ log "status = ${state} ${detail}"
70
+ }
71
+
72
+ die() { err "$*"; set_status FAILED "$*"; exit 1; }
73
+
74
+ require_root() { [[ $EUID -eq 0 ]] || die "run as root"; }
75
+
76
+ # A step must never die leaving status = RUNNING: the console follows this file.
77
+ _upgrade_on_err() {
78
+ local rc="$1" line="$2" cmd="$3" state
79
+ state=$(awk 'NR==1 {print $1}' "${UPGRADE_STATUS}" 2>/dev/null || true)
80
+ case "${state}" in
81
+ DONE|FAILED|WAITING-*) return 0 ;;
82
+ esac
83
+ err "unexpected failure (exit ${rc}) at line ${line}: ${cmd}"
84
+ set_status FAILED "line ${line}: ${cmd} (exit ${rc})"
85
+ }
86
+ trap '_upgrade_on_err "$?" "$LINENO" "$BASH_COMMAND"' ERR
87
+
88
+ # --- the node's own controls (always as the octra user) ---------------
89
+ as_octra() { su - "${NODE_USER}" -c "$*"; }
90
+
91
+ # node_script <timeout> <command...>: run one of the node's control scripts from
92
+ # the node directory as the node user, bounded so a control script that waits on
93
+ # the chain can never freeze a step. stdout+stderr are merged (what the operator
94
+ # needs to read).
95
+ node_script() {
96
+ local limit="$1"
97
+ shift
98
+ timeout "${limit}" su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && $*" 2>&1
99
+ }
100
+
101
+ # like node_script, but the caller decides what a non-zero exit means
102
+ node_script_rc() { # node_script_rc <timeout> <command...> -> prints output, returns the rc
103
+ local limit="$1" rc
104
+ shift
105
+ set +e
106
+ timeout "${limit}" su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && $*" 2>&1
107
+ rc=$?
108
+ set -e
109
+ return "${rc}"
110
+ }
111
+
112
+ stat_raw() { node_script "${STATE_TIMEOUT:-60}" "sh controls/stat.sh" || true; }
113
+
114
+ stat_field() { # an unreadable field is EMPTY, not the string "None" (see deploy/lib.sh)
115
+ awk -F' = ' -v k="$1" '$1 == k { if ($2 == "None" || $2 == "null") { print ""; exit } print $2; exit }'
116
+ }
117
+
118
+ # read_state: the fields every step here cares about (never writes anything on the
119
+ # node - stat.sh is read-only)
120
+ read_state() {
121
+ SNAP=$(stat_raw)
122
+ ROLE=$(printf '%s\n' "${SNAP}" | stat_field role)
123
+ PROCESS=$(printf '%s\n' "${SNAP}" | stat_field process)
124
+ RPC=$(printf '%s\n' "${SNAP}" | stat_field rpc)
125
+ VOTING=$(printf '%s\n' "${SNAP}" | stat_field voting)
126
+ EPOCH=$(printf '%s\n' "${SNAP}" | stat_field epoch)
127
+ ACTIVE=$(printf '%s\n' "${SNAP}" | stat_field validator_active)
128
+ SCHED=$(printf '%s\n' "${SNAP}" | stat_field validator_scheduled)
129
+ ENROLL=$(printf '%s\n' "${SNAP}" | stat_field validator_enrollment)
130
+ BINARY=$(printf '%s\n' "${SNAP}" | stat_field binary)
131
+ PVAC=$(printf '%s\n' "${SNAP}" | stat_field pvac_worker)
132
+ PROCESS_UP=$(printf '%s\n' "${SNAP}" | stat_field uptime)
133
+ }
134
+
135
+ # --- the checkout: what is really there -------------------------------
136
+ # The clone belongs to the node user, so `git` as root refuses with "dubious
137
+ # ownership": ask with an explicit safe.directory (same as deploy/lib.sh).
138
+ git_node() { # git_node <args...>
139
+ git -c safe.directory="${NODE_SRC_DIR}" -C "${NODE_SRC_DIR}" "$@" 2>/dev/null || true
140
+ }
141
+
142
+ source_commit() { # the commit the checkout SAYS it is (upstream file)
143
+ local out=""
144
+ [[ -f "${SOURCE_COMMIT_FILE}" ]] && out=$(head -c 64 "${SOURCE_COMMIT_FILE}" 2>/dev/null | tr -d '[:space:]' || true)
145
+ printf '%s' "${out}"
146
+ }
147
+
148
+ git_head() { git_node rev-parse --short HEAD | head -1; }
149
+ git_branch() {
150
+ local out
151
+ out=$(git_node rev-parse --abbrev-ref HEAD | head -1)
152
+ [[ "${out}" == "HEAD" ]] && out=""
153
+ printf '%s' "${out}"
154
+ }
155
+ git_dirty() { # 1 when the working tree has local changes (a build might depend on them)
156
+ local out
157
+ out=$(git_node status --porcelain | head -1)
158
+ [[ -n "${out}" ]] && printf '1'
159
+ return 0
160
+ }
161
+ git_remote() {
162
+ local out
163
+ out=$(git_node config --get remote.origin.url | head -1)
164
+ printf '%s' "${out:-https://github.com/octra-labs/lite_node.git}"
165
+ }
166
+
167
+ # --- tools the two update paths need ----------------------------------
168
+ ensure_build_tools() {
169
+ ensure_tool git git || die "git is missing and could not be installed"
170
+ ensure_tool make make || die "make is missing and could not be installed"
171
+ ensure_tool opam opam || die "opam is missing and could not be installed"
172
+ # the manual build compiles the C++/mcl part and needs a compiler
173
+ if ! command -v g++ >/dev/null 2>&1 && ! command -v c++ >/dev/null 2>&1; then
174
+ ensure_package build-essential || true
175
+ fi
176
+ }
177
+
178
+ # --- storage.sh (preserved states) ------------------------------------
179
+ storage_report() { # read-only: what the store holds right now
180
+ node_script "${STORAGE_TIMEOUT:-180}" "sh controls/storage.sh" || true
181
+ }
182
+
183
+ storage_summary() { # one line out of the report, for the status detail
184
+ # optional text: a report this version does not match must never fail the caller
185
+ storage_report | grep -iE 'preserved|reclaim|prior|free|used|total' | tail -3 \
186
+ | tr '\n' ' ' | sed 's/ */ /g' || true
187
+ return 0
188
+ }
189
+
190
+ # The report is emitted as `event = storage data_bytes = ... prior_count = ...`
191
+ # lines; the status detail only needs the few numbers that matter. Like
192
+ # storage_summary this is OPTIONAL text and must never return non-zero.
193
+ storage_fields() {
194
+ storage_report | grep -oE '(prior_count|prior_bytes|free_bytes|data_bytes) = [0-9]+' \
195
+ | tr '\n' ' ' | sed -e 's/ = /=/g' -e 's/ *$//' || true
196
+ return 0
197
+ }
198
+
199
+ # the wallet address of the node (read-only)
200
+ wallet_address() {
201
+ if [[ -f "${NODE_WALLET}" ]] && command -v jq >/dev/null 2>&1; then
202
+ jq -r '.address // empty' "${NODE_WALLET}" 2>/dev/null || true
203
+ fi
204
+ }
205
+
206
+ prune_states() { # the documented "Remove preserved states"
207
+ node_script_rc "${PRUNE_TIMEOUT:-900}" "sh controls/storage.sh --prune-prior --yes"
208
+ }
209
+
210
+ # --- what the upgrade tool answered -----------------------------------
211
+ # controls/upgrade.sh ends with a status line the README names: validator_active
212
+ # or observer_synced = fine, pending = do NOT restart and try later, refused =
213
+ # the reason is in the output.
214
+ upgrade_verdict() { # upgrade_verdict <output-file>
215
+ local file="$1"
216
+ [[ -f "${file}" ]] || return 0
217
+ awk '
218
+ /validator_active|observer_synced|status = pending|pending|refused/ {
219
+ if ($0 ~ /validator_active/) { print "validator_active"; exit }
220
+ if ($0 ~ /observer_synced/) { print "observer_synced"; exit }
221
+ if ($0 ~ /pending/) { print "pending"; exit }
222
+ if ($0 ~ /refused/) { print "refused"; exit }
223
+ }' "${file}" | tail -1
224
+ }
225
+
226
+ upgrade_reason() { # the last line that explains why (refused/pending)
227
+ local file="$1" line
228
+ [[ -f "${file}" ]] || return 0
229
+ line=$(grep -aiE 'status = (refused|pending)|reason = |error|denied|not allowed|dirty' "${file}" 2>/dev/null | tail -1 || true)
230
+ printf '%s' "${line##*: }"
231
+ }
232
+
package/bin/ovtools.js ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const path = require('path');
5
+ const fs = require('fs');
6
+
7
+ const distPath = path.join(__dirname, '..', 'dist', 'cli.js');
8
+ if (!fs.existsSync(distPath)) {
9
+ console.error('ovtools is not built (dist/cli.js is missing). Run: npm run build');
10
+ process.exit(1);
11
+ }
12
+
13
+ let cli;
14
+ try {
15
+ cli = require(distPath);
16
+ } catch (err) {
17
+ console.error('ovtools failed to load:', err && err.message ? err.message : err);
18
+ process.exit(1);
19
+ }
20
+
21
+ const main = cli && typeof cli.main === 'function' ? cli.main : null;
22
+ if (!main) {
23
+ console.error('ovtools is corrupted: dist/cli.js does not export main()');
24
+ process.exit(1);
25
+ }
26
+
27
+ main(process.argv.slice(2)).then(code => {
28
+ process.exitCode = typeof code === 'number' ? code : 0;
29
+ }).catch(err => {
30
+ console.error(`ERROR: ${err && err.message ? err.message : err}`);
31
+ process.exitCode = 1;
32
+ });
@@ -0,0 +1,6 @@
1
+ import type { CheckResult } from '../types';
2
+ export declare function runCheck(body: any): Promise<{
3
+ key: string;
4
+ result: CheckResult;
5
+ }>;
6
+ //# sourceMappingURL=checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/api/checks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,UAAU,CAAC;AAsFhE,wBAAsB,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC,CAwGvF"}