|
| 1 | +#!/usr/bin/env bash |
| 2 | +# |
| 3 | +# dev-common.sh — helpers specific to the NEAR One dev clusters (source, don't |
| 4 | +# run). Generic helpers live in ../common.sh. |
| 5 | +# |
| 6 | +# MPC_SIGN_WITH: use sign-with-legacy-keychain when the keychain can't find |
| 7 | +# a key written to ~/.near-credentials. |
| 8 | +# |
| 9 | + |
| 10 | +SIGN_WITH="${MPC_SIGN_WITH:-sign-with-keychain}" |
| 11 | + |
| 12 | +# Sets CONTRACT, NEAR_NET, MEMBER_ACCOUNTS, SIGN_DEPOSIT, and |
| 13 | +# re-points the endpoint vars from any exported per-cluster ones |
| 14 | +# (NOMAD_ADDR_DEV_TESTNET, ...), so the network choice drives every step. |
| 15 | +# Addresses themselves stay out of this repo. |
| 16 | +resolve_dev_cluster() { |
| 17 | + local suffix var |
| 18 | + case "$1" in |
| 19 | + testnet) |
| 20 | + CONTRACT="mpc-dev-contract.testnet" NEAR_NET="testnet" SIGN_DEPOSIT="1 NEAR" |
| 21 | + MEMBER_ACCOUNTS="mpc-node-0-mpc-dev.testnet mpc-node-1-mpc-dev.testnet" |
| 22 | + suffix="TESTNET" ;; |
| 23 | + mainnet) |
| 24 | + CONTRACT="dev-contract.near" NEAR_NET="mainnet" SIGN_DEPOSIT="0.1 NEAR" |
| 25 | + MEMBER_ACCOUNTS="mpc-0-dev-mainnet.dev-signer.near mpc-1-dev-mainnet.dev-signer.near" |
| 26 | + suffix="MAINNET" ;; |
| 27 | + *) die "Unknown dev cluster '$1' (expected testnet|mainnet)." ;; |
| 28 | + esac |
| 29 | + var="NOMAD_ADDR_DEV_${suffix}"; [[ -z "${!var:-}" ]] || export NOMAD_ADDR="${!var}" |
| 30 | + var="MPC_NODE_ADDRS_DEV_${suffix}"; [[ -z "${!var:-}" ]] || export MPC_NODE_ADDRS="${!var}" |
| 31 | + # +set: an intentionally empty value still disables the prompt. |
| 32 | + var="NOMAD_HTTP_AUTH_DEV_${suffix}"; [[ -z "${!var+set}" ]] || export NOMAD_HTTP_AUTH="${!var}" |
| 33 | +} |
| 34 | + |
| 35 | +# Typed in per run; the matching NOMAD_*_DEV_<NET> export skips the prompt. |
| 36 | +# Takes the bare IP — scheme and API path are the script's business. |
| 37 | +prompt_nomad_ip() { |
| 38 | + local label=${1:-target} input |
| 39 | + while [[ -z "${NOMAD_ADDR:-}" ]]; do |
| 40 | + read -rp "Nomad IP address for the ${label} dev cluster: " input |
| 41 | + # Tolerate a pasted URL. |
| 42 | + input="${input#http://}"; input="${input#https://}"; input="${input%%/*}" |
| 43 | + if [[ ! "$input" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}(:[0-9]+)?$ ]]; then |
| 44 | + echo " Expected an IPv4 address, optionally with a port (e.g. 10.0.0.1 or 10.0.0.1:4646)." |
| 45 | + continue |
| 46 | + fi |
| 47 | + NOMAD_ADDR="http://${input}" |
| 48 | + done |
| 49 | + export NOMAD_ADDR |
| 50 | +} |
| 51 | + |
| 52 | +prompt_http_auth() { |
| 53 | + local user pass |
| 54 | + read -rp "Nomad user for ${NOMAD_ADDR} (or user:password, blank for none): " user |
| 55 | + if [[ -z "$user" ]]; then |
| 56 | + NOMAD_HTTP_AUTH="" |
| 57 | + elif [[ "$user" == *:* ]]; then |
| 58 | + # Already joined — this form echoes the password to the terminal. |
| 59 | + NOMAD_HTTP_AUTH="$user" |
| 60 | + else |
| 61 | + read -rsp "Nomad password: " pass |
| 62 | + echo |
| 63 | + NOMAD_HTTP_AUTH="${user}:${pass}" |
| 64 | + fi |
| 65 | + export NOMAD_HTTP_AUTH |
| 66 | +} |
| 67 | + |
| 68 | +prompt_node_addrs() { |
| 69 | + local input |
| 70 | + [[ -z "${MPC_NODE_ADDRS+set}" ]] || return 0 |
| 71 | + read -rp "Node metrics addresses, space-separated (blank to skip verification): " input |
| 72 | + export MPC_NODE_ADDRS="$input" |
| 73 | +} |
| 74 | + |
| 75 | +# Whether a credential is configured — never the credential itself. |
| 76 | +nomad_auth_state() { |
| 77 | + if [[ -z "${NOMAD_HTTP_AUTH+set}" ]]; then echo "(will prompt)" |
| 78 | + elif [[ -n "$NOMAD_HTTP_AUTH" ]]; then echo "(set)" |
| 79 | + else echo "(none)"; fi |
| 80 | +} |
| 81 | + |
| 82 | +# Check every MPC_NODE_ADDRS node reports release="<version>". |
| 83 | +verify_nodes() { |
| 84 | + local version=$1 |
| 85 | + require_cmds curl |
| 86 | + [[ -n "${MPC_NODE_ADDRS:-}" ]] || die "MPC_NODE_ADDRS is not set (e.g. \"host:8080 host:8080\")." |
| 87 | + |
| 88 | + local addr info ok=0 fail=0 |
| 89 | + for addr in ${MPC_NODE_ADDRS}; do |
| 90 | + # The metrics listener is plain HTTP, internal-only; no TLS endpoint |
| 91 | + # exists to point at. |
| 92 | + # nosemgrep: trailofbits.generic.curl-unencrypted-url.curl-unencrypted-url |
| 93 | + show_cmd curl -sf "http://${addr}/metrics" '|' grep mpc_node_build_info |
| 94 | + # nosemgrep: trailofbits.generic.curl-unencrypted-url.curl-unencrypted-url |
| 95 | + info=$(curl -sf --max-time 5 "http://${addr}/metrics" \ |
| 96 | + | grep -o 'mpc_node_build_info{[^}]*}') || { echo " (unreachable)"; fail=1; continue; } |
| 97 | + echo " $info" |
| 98 | + if [[ "$info" == *"release=\"${version}\""* ]]; then ok=1; else fail=1; fi |
| 99 | + done |
| 100 | + if [[ "$fail" -eq 0 && "$ok" -eq 1 ]]; then |
| 101 | + ok "All nodes report release=\"${version}\"." |
| 102 | + else |
| 103 | + warn "Not all nodes are on ${version} yet." |
| 104 | + fi |
| 105 | +} |
| 106 | + |
| 107 | +# Test signature request against the cluster contract (on-chain txn). |
| 108 | +test_sign() { |
| 109 | + resolve_dev_cluster "$1" |
| 110 | + require_cmds near |
| 111 | + |
| 112 | + local signer=${MEMBER_ACCOUNTS%% *} |
| 113 | + local payload='[12,1,2,0,4,5,6,8,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,44]' |
| 114 | + local cmd=(near contract call-function as-transaction "$CONTRACT" sign |
| 115 | + json-args "{\"request\": {\"payload\": ${payload}, \"path\": \"test\", \"key_version\": 0}}" |
| 116 | + prepaid-gas '300.0 Tgas' attached-deposit "$SIGN_DEPOSIT" |
| 117 | + sign-as "$signer" network-config "$NEAR_NET" "$SIGN_WITH" send) |
| 118 | + |
| 119 | + echo "Test sign on ${CONTRACT} as ${signer} (deposit ${SIGN_DEPOSIT})." |
| 120 | + show_cmd "${cmd[@]}" |
| 121 | + confirm "Send it?" || return 0 |
| 122 | + if "${cmd[@]}"; then |
| 123 | + ok "Signature returned — the cluster is signing." |
| 124 | + else |
| 125 | + warn "Test sign failed — investigate before proceeding." |
| 126 | + fi |
| 127 | +} |
0 commit comments