remote-node.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. #!/usr/bin/env bash
  2. set -e
  3. cd "$(dirname "$0")"/../..
  4. set -x
  5. deployMethod="$1"
  6. nodeType="$2"
  7. entrypointIp="$3"
  8. numNodes="$4"
  9. if [[ -n $5 ]]; then
  10. export RUST_LOG="$5"
  11. fi
  12. skipSetup="$6"
  13. failOnValidatorBootupFailure="$7"
  14. externalPrimordialAccountsFile="$8"
  15. maybeDisableAirdrops="$9"
  16. internalNodesStakeLamports="${10}"
  17. internalNodesLamports="${11}"
  18. nodeIndex="${12}"
  19. numBenchTpsClients="${13}"
  20. benchTpsExtraArgs="${14}"
  21. genesisOptions="${15}"
  22. extraNodeArgs="${16}"
  23. maybeWarpSlot="${17}"
  24. maybeFullRpc="${18}"
  25. waitForNodeInit="${19}"
  26. extraPrimordialStakes="${20:=0}"
  27. tmpfsAccounts="${21:false}"
  28. disableQuic="${22}"
  29. enableUdp="${23}"
  30. maybeWenRestart="${24}"
  31. set +x
  32. missing() {
  33. echo "Error: $1 not specified"
  34. exit 1
  35. }
  36. [[ -n $deployMethod ]] || missing deployMethod
  37. [[ -n $nodeType ]] || missing nodeType
  38. [[ -n $entrypointIp ]] || missing entrypointIp
  39. [[ -n $numNodes ]] || missing numNodes
  40. [[ -n $skipSetup ]] || missing skipSetup
  41. [[ -n $failOnValidatorBootupFailure ]] || missing failOnValidatorBootupFailure
  42. airdropsEnabled=true
  43. if [[ -n $maybeDisableAirdrops ]]; then
  44. airdropsEnabled=false
  45. fi
  46. cat > deployConfig <<EOF
  47. deployMethod="$deployMethod"
  48. entrypointIp="$entrypointIp"
  49. numNodes="$numNodes"
  50. failOnValidatorBootupFailure=$failOnValidatorBootupFailure
  51. genesisOptions="$genesisOptions"
  52. airdropsEnabled=$airdropsEnabled
  53. EOF
  54. source net/common.sh
  55. source multinode-demo/common.sh
  56. loadConfigFile
  57. initCompleteFile=init-complete-node.log
  58. cat > ~/solana/on-reboot <<EOF
  59. #!/usr/bin/env bash
  60. cd ~/solana
  61. source scripts/oom-score-adj.sh
  62. now=\$(date -u +"%Y-%m-%dT%H:%M:%SZ")
  63. ln -sfT validator.log.\$now validator.log
  64. EOF
  65. chmod +x ~/solana/on-reboot
  66. case $deployMethod in
  67. local|tar|skip)
  68. PATH="$HOME"/.cargo/bin:"$PATH"
  69. export USE_INSTALL=1
  70. ./fetch-perf-libs.sh
  71. cat >> ~/solana/on-reboot <<EOF
  72. PATH="$HOME"/.cargo/bin:"$PATH"
  73. export USE_INSTALL=1
  74. (
  75. sudo SOLANA_METRICS_CONFIG="$SOLANA_METRICS_CONFIG" scripts/oom-monitor.sh
  76. ) > oom-monitor.log 2>&1 &
  77. echo \$! > oom-monitor.pid
  78. scripts/fd-monitor.sh > fd-monitor.log 2>&1 &
  79. echo \$! > fd-monitor.pid
  80. scripts/net-stats.sh > net-stats.log 2>&1 &
  81. echo \$! > net-stats.pid
  82. scripts/iftop.sh > iftop.log 2>&1 &
  83. echo \$! > iftop.pid
  84. scripts/system-stats.sh > system-stats.log 2>&1 &
  85. echo \$! > system-stats.pid
  86. EOF
  87. case $nodeType in
  88. bootstrap-validator)
  89. set -x
  90. if [[ $skipSetup != true ]]; then
  91. clear_config_dir "$SOLANA_CONFIG_DIR"
  92. if [[ -n $internalNodesLamports ]]; then
  93. echo "---" >> config/validator-balances.yml
  94. fi
  95. setupValidatorKeypair() {
  96. declare name=$1
  97. if [[ -f net/keypairs/"$name".json ]]; then
  98. cp net/keypairs/"$name".json config/"$name".json
  99. if [[ "$name" =~ ^validator-identity- ]]; then
  100. name="${name//-identity-/-vote-}"
  101. cp net/keypairs/"$name".json config/"$name".json
  102. name="${name//-vote-/-stake-}"
  103. cp net/keypairs/"$name".json config/"$name".json
  104. fi
  105. else
  106. solana-keygen new --no-passphrase -so config/"$name".json
  107. if [[ "$name" =~ ^validator-identity- ]]; then
  108. name="${name//-identity-/-vote-}"
  109. solana-keygen new --no-passphrase -so config/"$name".json
  110. name="${name//-vote-/-stake-}"
  111. solana-keygen new --no-passphrase -so config/"$name".json
  112. fi
  113. fi
  114. if [[ -n $internalNodesLamports ]]; then
  115. declare pubkey
  116. pubkey="$(solana-keygen pubkey config/"$name".json)"
  117. cat >> config/validator-balances.yml <<EOF
  118. $pubkey:
  119. balance: $internalNodesLamports
  120. owner: 11111111111111111111111111111111
  121. data:
  122. executable: false
  123. EOF
  124. fi
  125. }
  126. for i in $(seq 1 "$numNodes"); do
  127. setupValidatorKeypair validator-identity-"$i"
  128. done
  129. setupValidatorKeypair blockstreamer-identity
  130. lamports_per_signature="42"
  131. # shellcheck disable=SC2206 # Do not want to quote $genesisOptions
  132. genesis_args=($genesisOptions)
  133. for i in "${!genesis_args[@]}"; do
  134. if [[ "${genesis_args[$i]}" = --target-lamports-per-signature ]]; then
  135. lamports_per_signature="${genesis_args[$((i+1))]}"
  136. break
  137. fi
  138. done
  139. for i in $(seq 0 $((numBenchTpsClients-1))); do
  140. # shellcheck disable=SC2086 # Do not want to quote $benchTpsExtraArgs
  141. solana-bench-tps --write-client-keys config/bench-tps"$i".yml \
  142. --target-lamports-per-signature "$lamports_per_signature" $benchTpsExtraArgs
  143. # Skip first line, as it contains header
  144. tail -n +2 -q config/bench-tps"$i".yml >> config/client-accounts.yml
  145. echo "" >> config/client-accounts.yml
  146. done
  147. if [[ -f $externalPrimordialAccountsFile ]]; then
  148. cat "$externalPrimordialAccountsFile" >> config/validator-balances.yml
  149. fi
  150. if [[ -f config/validator-balances.yml ]]; then
  151. genesisOptions+=" --primordial-accounts-file config/validator-balances.yml"
  152. fi
  153. if [[ -f config/client-accounts.yml ]]; then
  154. genesisOptions+=" --primordial-accounts-file config/client-accounts.yml"
  155. fi
  156. if [[ -n $internalNodesStakeLamports ]]; then
  157. args+=(--bootstrap-validator-stake-lamports "$internalNodesStakeLamports")
  158. fi
  159. if [[ -n $internalNodesLamports ]]; then
  160. args+=(--bootstrap-validator-lamports "$internalNodesLamports")
  161. fi
  162. # shellcheck disable=SC2206 # Do not want to quote $genesisOptions
  163. args+=($genesisOptions)
  164. if [[ -f net/keypairs/faucet.json ]]; then
  165. export FAUCET_KEYPAIR=net/keypairs/faucet.json
  166. fi
  167. if [[ -f net/keypairs/bootstrap-validator-identity.json ]]; then
  168. export BOOTSTRAP_VALIDATOR_IDENTITY_KEYPAIR=net/keypairs/bootstrap-validator-identity.json
  169. fi
  170. if [[ -f net/keypairs/bootstrap-validator-stake.json ]]; then
  171. export BOOTSTRAP_VALIDATOR_STAKE_KEYPAIR=net/keypairs/bootstrap-validator-stake.json
  172. fi
  173. if [[ -f net/keypairs/bootstrap-validator-vote.json ]]; then
  174. export BOOTSTRAP_VALIDATOR_VOTE_KEYPAIR=net/keypairs/bootstrap-validator-vote.json
  175. fi
  176. echo "remote-node.sh: Primordial stakes: $extraPrimordialStakes"
  177. if [[ "$extraPrimordialStakes" -gt 0 ]]; then
  178. if [[ "$extraPrimordialStakes" -gt "$numNodes" ]]; then
  179. echo "warning: extraPrimordialStakes($extraPrimordialStakes) clamped to numNodes($numNodes)"
  180. extraPrimordialStakes=$numNodes
  181. fi
  182. for i in $(seq "$extraPrimordialStakes"); do
  183. args+=(--bootstrap-validator "$(solana-keygen pubkey "config/validator-identity-$i.json")"
  184. "$(solana-keygen pubkey "config/validator-vote-$i.json")"
  185. "$(solana-keygen pubkey "config/validator-stake-$i.json")"
  186. )
  187. done
  188. fi
  189. multinode-demo/setup.sh "${args[@]}"
  190. maybeWaitForSupermajority=
  191. # shellcheck disable=SC2086 # Do not want to quote $extraNodeArgs
  192. set -- $extraNodeArgs
  193. while [[ -n $1 ]]; do
  194. if [[ $1 = "--wait-for-supermajority" ]]; then
  195. maybeWaitForSupermajority=$2
  196. break
  197. fi
  198. shift
  199. done
  200. if [[ -z "$maybeWarpSlot" && -n "$maybeWaitForSupermajority" ]]; then
  201. maybeWarpSlot="--warp-slot $maybeWaitForSupermajority"
  202. fi
  203. if [[ -n "$maybeWarpSlot" ]]; then
  204. # shellcheck disable=SC2086 # Do not want to quote $maybeWarSlot
  205. agave-ledger-tool -l config/bootstrap-validator create-snapshot 0 config/bootstrap-validator $maybeWarpSlot
  206. fi
  207. agave-ledger-tool -l config/bootstrap-validator shred-version --max-genesis-archive-unpacked-size 1073741824 | tee config/shred-version
  208. if [[ -n "$maybeWaitForSupermajority" ]]; then
  209. bankHash=$(agave-ledger-tool -l config/bootstrap-validator verify --halt-at-slot 0 --print-bank-hash --output json | jq -r ".hash")
  210. shredVersion="$(cat "$SOLANA_CONFIG_DIR"/shred-version)"
  211. extraNodeArgs="$extraNodeArgs --expected-bank-hash $bankHash --expected-shred-version $shredVersion"
  212. echo "$bankHash" > config/bank-hash
  213. fi
  214. fi
  215. args=(
  216. --bind-address "$entrypointIp"
  217. --gossip-port 8001
  218. --init-complete-file "$initCompleteFile"
  219. )
  220. if [[ "$tmpfsAccounts" = "true" ]]; then
  221. args+=(--accounts /mnt/solana-accounts)
  222. fi
  223. if $maybeFullRpc; then
  224. args+=(--enable-rpc-transaction-history)
  225. args+=(--enable-extended-tx-metadata-storage)
  226. fi
  227. if $disableQuic; then
  228. args+=(--tpu-disable-quic)
  229. fi
  230. if $enableUdp; then
  231. args+=(--tpu-enable-udp)
  232. fi
  233. if [[ $airdropsEnabled = true ]]; then
  234. cat >> ~/solana/on-reboot <<EOF
  235. ./multinode-demo/faucet.sh > faucet.log 2>&1 &
  236. EOF
  237. fi
  238. if [[ -n "$maybeWenRestart" ]]; then
  239. args+=(--wen-restart "$maybeWenRestart")
  240. fi
  241. # shellcheck disable=SC2206 # Don't want to double quote $extraNodeArgs
  242. args+=($extraNodeArgs)
  243. cat >> ~/solana/on-reboot <<EOF
  244. nohup ./multinode-demo/bootstrap-validator.sh ${args[@]} > validator.log.\$now 2>&1 &
  245. pid=\$!
  246. oom_score_adj "\$pid" 1000
  247. disown
  248. EOF
  249. ~/solana/on-reboot
  250. if $waitForNodeInit; then
  251. net/remote/remote-node-wait-init.sh 600
  252. fi
  253. ;;
  254. validator|blockstreamer)
  255. if [[ $deployMethod != skip ]]; then
  256. net/scripts/rsync-retry.sh -vPrc "$entrypointIp":~/.cargo/bin/ ~/.cargo/bin/
  257. net/scripts/rsync-retry.sh -vPrc "$entrypointIp":~/version.yml ~/version.yml
  258. fi
  259. if [[ $skipSetup != true ]]; then
  260. clear_config_dir "$SOLANA_CONFIG_DIR"
  261. if [[ $nodeType = blockstreamer ]]; then
  262. net/scripts/rsync-retry.sh -vPrc \
  263. "$entrypointIp":~/solana/config/blockstreamer-identity.json "$SOLANA_CONFIG_DIR"/validator-identity.json
  264. else
  265. net/scripts/rsync-retry.sh -vPrc \
  266. "$entrypointIp":~/solana/config/validator-identity-"$nodeIndex".json "$SOLANA_CONFIG_DIR"/validator-identity.json
  267. net/scripts/rsync-retry.sh -vPrc \
  268. "$entrypointIp":~/solana/config/validator-stake-"$nodeIndex".json "$SOLANA_CONFIG_DIR"/stake-account.json
  269. net/scripts/rsync-retry.sh -vPrc \
  270. "$entrypointIp":~/solana/config/validator-vote-"$nodeIndex".json "$SOLANA_CONFIG_DIR"/vote-account.json
  271. fi
  272. net/scripts/rsync-retry.sh -vPrc \
  273. "$entrypointIp":~/solana/config/shred-version "$SOLANA_CONFIG_DIR"/shred-version
  274. net/scripts/rsync-retry.sh -vPrc \
  275. "$entrypointIp":~/solana/config/bank-hash "$SOLANA_CONFIG_DIR"/bank-hash || true
  276. net/scripts/rsync-retry.sh -vPrc \
  277. "$entrypointIp":~/solana/config/faucet.json "$SOLANA_CONFIG_DIR"/faucet.json
  278. fi
  279. args=(
  280. --entrypoint "$entrypointIp:8001"
  281. --gossip-port 8001
  282. --rpc-port 8899
  283. --expected-shred-version "$(cat "$SOLANA_CONFIG_DIR"/shred-version)"
  284. )
  285. if [[ $nodeType = blockstreamer ]]; then
  286. args+=(
  287. --blockstream /tmp/solana-blockstream.sock
  288. --no-voting
  289. --dev-no-sigverify
  290. --enable-rpc-transaction-history
  291. )
  292. else
  293. if [[ -n $internalNodesLamports ]]; then
  294. args+=(--node-lamports "$internalNodesLamports")
  295. fi
  296. fi
  297. if [[ ! -f "$SOLANA_CONFIG_DIR"/validator-identity.json ]]; then
  298. solana-keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/validator-identity.json
  299. fi
  300. args+=(--identity "$SOLANA_CONFIG_DIR"/validator-identity.json)
  301. if [[ ! -f "$SOLANA_CONFIG_DIR"/vote-account.json ]]; then
  302. solana-keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/vote-account.json
  303. fi
  304. args+=(--vote-account "$SOLANA_CONFIG_DIR"/vote-account.json)
  305. if [[ $airdropsEnabled != true ]]; then
  306. args+=(--no-airdrop)
  307. else
  308. args+=(--rpc-faucet-address "$entrypointIp:9900")
  309. fi
  310. if [[ -r "$SOLANA_CONFIG_DIR"/bank-hash ]]; then
  311. args+=(--expected-bank-hash "$(cat "$SOLANA_CONFIG_DIR"/bank-hash)")
  312. fi
  313. set -x
  314. # Add the faucet keypair to validators for convenient access from tools
  315. # like bench-tps and add to blocktreamers to run a faucet
  316. scp "$entrypointIp":~/solana/config/faucet.json "$SOLANA_CONFIG_DIR"/
  317. if [[ $nodeType = blockstreamer ]]; then
  318. # Run another faucet with the same keypair on the blockstreamer node.
  319. # Typically the blockstreamer node has a static IP/DNS name for hosting
  320. # the blockexplorer web app, and is a location that somebody would expect
  321. # to be able to airdrop from
  322. if [[ $airdropsEnabled = true ]]; then
  323. cat >> ~/solana/on-reboot <<EOF
  324. multinode-demo/faucet.sh > faucet.log 2>&1 &
  325. EOF
  326. fi
  327. # Grab the TLS cert generated by /certbot-restore.sh
  328. if [[ -f /.cert.pem ]]; then
  329. sudo install -o $UID -m 400 /.cert.pem /.key.pem .
  330. ls -l .cert.pem .key.pem
  331. fi
  332. fi
  333. args+=(--init-complete-file "$initCompleteFile")
  334. # shellcheck disable=SC2206 # Don't want to double quote $extraNodeArgs
  335. args+=($extraNodeArgs)
  336. maybeSkipAccountsCreation=
  337. if [[ $nodeIndex -le $extraPrimordialStakes ]]; then
  338. maybeSkipAccountsCreation="export SKIP_ACCOUNTS_CREATION=1"
  339. fi
  340. if [[ "$tmpfsAccounts" = "true" ]]; then
  341. args+=(--accounts /mnt/solana-accounts)
  342. fi
  343. if $maybeFullRpc; then
  344. args+=(--enable-rpc-transaction-history)
  345. args+=(--enable-extended-tx-metadata-storage)
  346. fi
  347. if $disableQuic; then
  348. args+=(--tpu-disable-quic)
  349. fi
  350. if $enableUdp; then
  351. args+=(--tpu-enable-udp)
  352. fi
  353. if [[ -n "$maybeWenRestart" ]]; then
  354. args+=(--wen-restart wen_restart.proto3)
  355. args+=(--wen-restart-coordinator "$maybeWenRestart")
  356. fi
  357. cat >> ~/solana/on-reboot <<EOF
  358. $maybeSkipAccountsCreation
  359. nohup multinode-demo/validator.sh ${args[@]} > validator.log.\$now 2>&1 &
  360. pid=\$!
  361. oom_score_adj "\$pid" 1000
  362. disown
  363. EOF
  364. ~/solana/on-reboot
  365. if $waitForNodeInit; then
  366. net/remote/remote-node-wait-init.sh 600
  367. fi
  368. if [[ $skipSetup != true && $nodeType != blockstreamer && -z $maybeSkipAccountsCreation ]]; then
  369. # Wait for the validator to catch up to the bootstrap validator before
  370. # delegating stake to it
  371. solana --url http://"$entrypointIp":8899 catchup config/validator-identity.json
  372. args=(
  373. --url http://"$entrypointIp":8899
  374. )
  375. if [[ $airdropsEnabled != true ]]; then
  376. args+=(--no-airdrop)
  377. fi
  378. if [[ -f config/validator-identity.json ]]; then
  379. args+=(--keypair config/validator-identity.json)
  380. fi
  381. if [[ ${extraPrimordialStakes} -eq 0 ]]; then
  382. echo "0 Primordial stakes, staking with $internalNodesStakeLamports"
  383. multinode-demo/delegate-stake.sh --vote-account "$SOLANA_CONFIG_DIR"/vote-account.json \
  384. --stake-account "$SOLANA_CONFIG_DIR"/stake-account.json \
  385. --force \
  386. "${args[@]}" "$internalNodesStakeLamports"
  387. else
  388. echo "Skipping staking with extra stakes: ${extraPrimordialStakes}"
  389. fi
  390. fi
  391. ;;
  392. *)
  393. echo "Error: unknown node type: $nodeType"
  394. exit 1
  395. ;;
  396. esac
  397. ;;
  398. *)
  399. echo "Unknown deployment method: $deployMethod"
  400. exit 1
  401. esac