2019-05-23 15:06:01 -07:00
#!/usr/bin/env bash
2019-07-30 22:43:47 -07:00
#
# Start a validator
#
2019-05-23 15:06:01 -07:00
here = $( dirname " $0 " )
2019-07-30 22:43:47 -07:00
# shellcheck source=multinode-demo/common.sh
source " $here " /common.sh
2019-12-10 17:52:35 -05:00
args = ( )
airdrops_enabled = 1
node_lamports = 500000000000 # 500 SOL: number of lamports to airdrop the node for transaction fees and vote account rent exemption (ignored if airdrops_enabled=0)
label =
identity_keypair_path =
voting_keypair_path =
no_restart = 0
gossip_entrypoint =
ledger_dir =
2019-08-01 13:48:00 -07:00
usage( ) {
2019-07-30 22:43:47 -07:00
if [ [ -n $1 ] ] ; then
echo " $* "
echo
fi
cat <<EOF
2019-08-01 13:48:00 -07:00
usage: $0 [ OPTIONS] [ cluster entry point hostname]
2019-07-30 22:43:47 -07:00
2019-08-01 13:48:00 -07:00
Start a validator with no stake
2019-07-30 22:43:47 -07:00
2019-08-01 13:48:00 -07:00
OPTIONS:
2019-08-05 12:42:52 -07:00
--ledger PATH - store ledger under this PATH
2019-07-30 22:43:47 -07:00
--blockstream PATH - open blockstream at this unix domain socket location
--init-complete-file FILE - create this file, if it doesn' t already exist, once node initialization is complete
--label LABEL - Append the given label to the configuration files, useful when running
2019-08-01 13:48:00 -07:00
multiple validators in the same workspace
2019-12-10 17:52:35 -05:00
--node-lamports LAMPORTS - Number of lamports this node has been funded from the genesis config ( default: $node_lamports )
2019-07-30 22:43:47 -07:00
--no-voting - start node without vote signer
--rpc-port port - custom RPC port for this node
--no-restart - do not restart the node if it exits
2019-11-08 23:56:57 -05:00
--no-airdrop - The genesis config has an account for the node. Airdrops are not required.
2019-07-30 22:43:47 -07:00
EOF
exit 1
}
positional_args = ( )
while [ [ -n $1 ] ] ; do
if [ [ ${ 1 : 0 : 1 } = - ] ] ; then
2019-09-05 15:57:35 -06:00
# validator.sh-only options
2019-07-30 22:43:47 -07:00
if [ [ $1 = --label ] ] ; then
label = " - $2 "
shift 2
elif [ [ $1 = --no-restart ] ] ; then
no_restart = 1
shift
2019-09-05 15:57:35 -06:00
elif [ [ $1 = --node-lamports ] ] ; then
node_lamports = " $2 "
2019-07-30 22:43:47 -07:00
shift 2
2019-09-05 15:57:35 -06:00
elif [ [ $1 = --no-airdrop ] ] ; then
airdrops_enabled = 0
shift
# solana-validator options
elif [ [ $1 = --blockstream ] ] ; then
2019-07-31 09:54:39 -07:00
args += ( " $1 " " $2 " )
shift 2
2019-11-08 23:56:57 -05:00
elif [ [ $1 = --expected-genesis-hash ] ] ; then
2019-09-29 19:09:24 -07:00
args += ( " $1 " " $2 " )
shift 2
2019-11-22 10:20:40 -05:00
elif [ [ $1 = --identity-keypair ] ] ; then
2019-07-30 22:43:47 -07:00
identity_keypair_path = $2
args += ( " $1 " " $2 " )
shift 2
elif [ [ $1 = --voting-keypair ] ] ; then
voting_keypair_path = $2
args += ( " $1 " " $2 " )
shift 2
2019-09-05 15:57:35 -06:00
elif [ [ $1 = --vote-account ] ] ; then
args += ( " $1 " " $2 " )
shift 2
2019-07-30 22:43:47 -07:00
elif [ [ $1 = --storage-keypair ] ] ; then
storage_keypair_path = $2
args += ( " $1 " " $2 " )
shift 2
elif [ [ $1 = --init-complete-file ] ] ; then
args += ( " $1 " " $2 " )
shift 2
2019-09-05 15:57:35 -06:00
elif [ [ $1 = --ledger ] ] ; then
ledger_dir = $2
shift 2
elif [ [ $1 = --entrypoint ] ] ; then
gossip_entrypoint = $2
args += ( " $1 " " $2 " )
2019-07-30 22:43:47 -07:00
shift 2
2019-08-14 19:25:22 -07:00
elif [ [ $1 = --no-snapshot-fetch ] ] ; then
args += ( " $1 " )
shift
2019-07-30 22:43:47 -07:00
elif [ [ $1 = --no-voting ] ] ; then
args += ( " $1 " )
shift
2019-08-08 09:14:30 -07:00
elif [ [ $1 = --dev-no-sigverify ] ] ; then
2019-07-30 22:43:47 -07:00
args += ( " $1 " )
shift
2019-09-05 15:57:35 -06:00
elif [ [ $1 = --dev-halt-at-slot ] ] ; then
args += ( " $1 " " $2 " )
shift 2
elif [ [ $1 = --rpc-port ] ] ; then
args += ( " $1 " " $2 " )
shift 2
elif [ [ $1 = --enable-rpc-exit ] ] ; then
2019-07-30 22:43:47 -07:00
args += ( " $1 " )
shift
2019-12-16 14:05:17 -07:00
elif [ [ $1 = --rpc-faucet-address ] ] ; then
2019-07-30 22:43:47 -07:00
args += ( " $1 " " $2 " )
shift 2
2019-09-05 15:57:35 -06:00
elif [ [ $1 = --vote-signer-address ] ] ; then
args += ( " $1 " " $2 " )
shift 2
elif [ [ $1 = --accounts ] ] ; then
2019-07-30 22:43:47 -07:00
args += ( " $1 " " $2 " )
shift 2
elif [ [ $1 = --gossip-port ] ] ; then
args += ( " $1 " " $2 " )
shift 2
2019-09-05 15:57:35 -06:00
elif [ [ $1 = --dynamic-port-range ] ] ; then
args += ( " $1 " " $2 " )
shift 2
elif [ [ $1 = --snapshot-interval-slots ] ] ; then
args += ( " $1 " " $2 " )
2019-07-30 22:43:47 -07:00
shift 2
2019-09-05 15:57:35 -06:00
elif [ [ $1 = --limit-ledger-size ] ] ; then
args += ( " $1 " )
shift
2019-11-04 22:14:55 -07:00
elif [ [ $1 = --skip-poh-verify ] ] ; then
2019-09-05 15:57:35 -06:00
args += ( " $1 " )
shift
2019-11-06 12:47:34 -07:00
elif [ [ $1 = --log ] ] ; then
args += ( " $1 " " $2 " )
shift 2
2019-07-30 22:43:47 -07:00
elif [ [ $1 = -h ] ] ; then
2019-08-01 13:48:00 -07:00
usage " $@ "
2019-07-30 22:43:47 -07:00
else
echo " Unknown argument: $1 "
exit 1
fi
else
positional_args += ( " $1 " )
shift
fi
done
2019-10-14 10:33:32 -06:00
if [ [ " $SOLANA_GPU_MISSING " -eq 1 ] ] ; then
echo "Testnet requires GPUs, but none were found! Aborting..."
exit 1
fi
2019-07-30 22:43:47 -07:00
if [ [ ${# positional_args [@] } -gt 1 ] ] ; then
2019-08-01 13:48:00 -07:00
usage " $@ "
2019-07-30 22:43:47 -07:00
fi
2019-08-05 12:42:52 -07:00
if [ [ -n $REQUIRE_LEDGER_DIR ] ] ; then
if [ [ -z $ledger_dir ] ] ; then
usage "Error: --ledger not specified"
2019-07-30 22:43:47 -07:00
fi
2019-08-05 12:42:52 -07:00
SOLANA_CONFIG_DIR = " $ledger_dir "
2019-07-30 22:43:47 -07:00
fi
2019-08-05 10:39:16 -07:00
if [ [ -n $REQUIRE_KEYPAIRS ] ] ; then
if [ [ -z $identity_keypair_path ] ] ; then
2019-11-22 10:20:40 -05:00
usage "Error: --identity-keypair not specified"
2019-08-05 10:39:16 -07:00
fi
if [ [ -z $voting_keypair_path ] ] ; then
usage "Error: --voting-keypair not specified"
fi
fi
2019-08-05 12:42:52 -07:00
if [ [ -z " $ledger_dir " ] ] ; then
ledger_dir = " $SOLANA_CONFIG_DIR /validator $label "
2019-07-30 22:43:47 -07:00
fi
2019-08-05 12:42:52 -07:00
mkdir -p " $ledger_dir "
2019-07-30 22:43:47 -07:00
2019-07-31 09:54:39 -07:00
if [ [ -n $gossip_entrypoint ] ] ; then
# Prefer the --entrypoint argument if supplied...
if [ [ ${# positional_args [@] } -gt 0 ] ] ; then
2019-08-01 13:48:00 -07:00
usage " $@ "
2019-07-31 09:54:39 -07:00
fi
else
# ...but also support providing the entrypoint's hostname as the first
# positional argument
entrypoint_hostname = ${ positional_args [0] }
if [ [ -z $entrypoint_hostname ] ] ; then
gossip_entrypoint = 127.0.0.1:8001
else
gossip_entrypoint = " $entrypoint_hostname " :8001
fi
2019-07-30 22:43:47 -07:00
fi
2019-08-13 10:49:48 -07:00
2019-12-16 14:05:17 -07:00
faucet_address = " ${ gossip_entrypoint % : * } " :9900
2019-07-30 22:43:47 -07:00
2019-08-05 12:42:52 -07:00
: " ${ identity_keypair_path : = $ledger_dir /identity-keypair.json } "
: " ${ voting_keypair_path : = $ledger_dir /vote-keypair.json } "
: " ${ storage_keypair_path : = $ledger_dir /storage-keypair.json } "
2019-07-30 22:43:47 -07:00
default_arg --entrypoint " $gossip_entrypoint "
if ( ( airdrops_enabled) ) ; then
2019-12-16 14:05:17 -07:00
default_arg --rpc-faucet-address " $faucet_address "
2019-07-30 22:43:47 -07:00
fi
2019-11-22 10:20:40 -05:00
default_arg --identity-keypair " $identity_keypair_path "
2019-07-30 22:43:47 -07:00
default_arg --voting-keypair " $voting_keypair_path "
default_arg --storage-keypair " $storage_keypair_path "
2019-08-05 12:42:52 -07:00
default_arg --ledger " $ledger_dir "
2019-11-06 12:47:34 -07:00
default_arg --log -
2019-07-30 22:43:47 -07:00
if [ [ -n $SOLANA_CUDA ] ] ; then
program = $solana_validator_cuda
else
program = $solana_validator
fi
set -e
PS4 = " $( basename " $0 " ) : "
pid =
kill_node( ) {
# Note: do not echo anything from this function to ensure $pid is actually
# killed when stdout/stderr are redirected
set +ex
if [ [ -n $pid ] ] ; then
declare _pid = $pid
pid =
kill " $_pid " || true
wait " $_pid " || true
fi
}
2019-09-06 15:08:30 -06:00
2019-07-30 22:43:47 -07:00
kill_node_and_exit( ) {
kill_node
exit
}
2019-09-06 15:08:30 -06:00
2019-07-30 22:43:47 -07:00
trap 'kill_node_and_exit' INT TERM ERR
2019-08-05 12:42:52 -07:00
wallet( ) {
(
set -x
2019-08-22 13:51:16 -07:00
$solana_cli --keypair " $identity_keypair_path " --url " $rpc_url " " $@ "
2019-08-05 12:42:52 -07:00
)
}
setup_validator_accounts( ) {
declare node_lamports = $1
2020-01-20 23:06:47 -07:00
if ! wallet vote-account " $voting_keypair_path " ; then
2019-09-19 22:33:35 -07:00
if ( ( airdrops_enabled) ) ; then
echo " Adding $node_lamports to validator identity account: "
wallet airdrop " $node_lamports " lamports || return $?
fi
2019-08-05 12:42:52 -07:00
echo "Creating validator vote account"
2020-01-14 23:29:41 -07:00
wallet create-vote-account " $voting_keypair_path " " $identity_keypair_path " || return $?
2019-08-05 12:42:52 -07:00
fi
echo "Validator vote account configured"
2020-01-20 23:06:47 -07:00
if ! wallet storage-account " $storage_keypair_path " ; then
2019-08-05 12:42:52 -07:00
echo "Creating validator storage account"
2019-08-10 13:15:59 -07:00
wallet create-validator-storage-account " $identity_keypair_path " " $storage_keypair_path " || return $?
2019-08-05 12:42:52 -07:00
fi
echo "Validator storage account configured"
2019-09-19 22:33:35 -07:00
echo "Validator identity account balance:"
wallet balance --lamports || return $?
2019-08-05 12:42:52 -07:00
return 0
}
2020-01-20 23:06:47 -07:00
rpc_url = $( $solana_gossip rpc-url --entrypoint " $gossip_entrypoint " --any)
2019-11-22 09:44:16 -07:00
2019-11-25 23:33:15 -05:00
[ [ -r " $identity_keypair_path " ] ] || $solana_keygen new --no-passphrase -so " $identity_keypair_path "
[ [ -r " $voting_keypair_path " ] ] || $solana_keygen new --no-passphrase -so " $voting_keypair_path "
[ [ -r " $storage_keypair_path " ] ] || $solana_keygen new --no-passphrase -so " $storage_keypair_path "
2019-07-30 22:43:47 -07:00
2019-11-22 09:44:16 -07:00
setup_validator_accounts " $node_lamports "
2019-08-05 12:42:52 -07:00
2019-11-22 09:44:16 -07:00
while true; do
2019-07-30 22:43:47 -07:00
echo " $PS4 $program ${ args [*] } "
$program " ${ args [@] } " &
pid = $!
echo " pid: $pid "
if ( ( no_restart) ) ; then
wait " $pid "
exit $?
fi
while true; do
if [ [ -z $pid ] ] || ! kill -0 " $pid " ; then
echo "############## validator exited, restarting ##############"
break
fi
sleep 1
done
kill_node
done