Last active
October 13, 2024 21:29
-
-
Save Commoneffort/ffeee28f1129867377bfbd8dc29066de to your computer and use it in GitHub Desktop.
X1 validator installation and setup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Exit on any error | |
set -e | |
# Define variables | |
RELEASE_TAG="v1.18.23" | |
BIN_DIR="$HOME/.local/share/solana/bin" | |
SOLANA_INSTALL_DIR="$HOME/.local/share/solana/install/active_release" | |
SYSCTL_CONF_FILE="/etc/sysctl.d/21-solana-validator.conf" | |
LIMITS_CONF_FILE="/etc/security/limits.d/90-solana-nofiles.conf" | |
SOLANA_INSTALL_SCRIPT="https://release.solana.com/v1.18.23/install" | |
GIT_REPO="https://github.com/jacklevin74/xolana.git" | |
GIT_DIR="$HOME/xolana" | |
LEDGER_DIR="$HOME/ledger" | |
KEYPAIR_PATH="$HOME/.config/solana/id.json" | |
MAX_ATTEMPTS=3 | |
CATCHUP_TIMEOUT=60 # 1 minute in seconds | |
# Function to display errors | |
err() { | |
echo "$1" >&2 | |
exit 1 | |
} | |
# Update package list and install necessary packages | |
echo "Updating package list..." | |
sudo apt-get update | |
echo "Installing build dependencies..." | |
sudo apt-get install -y \ | |
gcc \ | |
make \ | |
curl \ | |
wget \ | |
pkg-config \ | |
libudev-dev \ | |
rustc \ | |
cargo \ | |
clang \ | |
libclang-dev \ | |
protobuf-compiler \ | |
libssl-dev \ | |
zlib1g-dev \ | |
llvm \ | |
cmake \ | |
libprotobuf-dev \ | |
libprotobuf-c-dev | |
# Create directory for Solana binary if it doesn't exist | |
mkdir -p "$BIN_DIR" | |
# Update PATH for Solana build | |
echo "Updating PATH for Solana build..." | |
export PATH="$BIN_DIR:$PATH" | |
if ! grep -q 'export PATH="$HOME/.local/share/solana/bin:$PATH"' ~/.bashrc; then | |
echo 'export PATH="$HOME/.local/share/solana/bin:$PATH"' >> ~/.bashrc | |
fi | |
source ~/.bashrc | |
# Install Solana Release | |
echo "Installing Solana release v1.18.23..." | |
sh -c "$(curl -sSfL $SOLANA_INSTALL_SCRIPT)" | |
# Update PATH for Solana release | |
echo "Updating PATH for Solana release..." | |
export PATH="$SOLANA_INSTALL_DIR/bin:$PATH" | |
if ! grep -q "export PATH=\"$SOLANA_INSTALL_DIR/bin:$PATH\"" ~/.bashrc; then | |
echo "export PATH=\"$SOLANA_INSTALL_DIR/bin:$PATH\"" >> ~/.bashrc | |
fi | |
source ~/.bashrc | |
# System Tuning (Skip if setrlimit fails) | |
echo "Optimizing sysctl knobs..." | |
sudo bash -c "cat > $SYSCTL_CONF_FILE <<EOF | |
# Increase UDP buffer sizes | |
net.core.rmem_default = 134217728 | |
net.core.rmem_max = 134217728 | |
net.core.wmem_default = 134217728 | |
net.core.wmem_max = 134217728 | |
# Increase memory mapped files limit | |
vm.max_map_count = 1000000 | |
# Increase number of allowed open file descriptors | |
fs.nr_open = 1000000 | |
EOF" || echo "Failed to apply sysctl knobs. Skipping..." | |
sudo sysctl -p $SYSCTL_CONF_FILE || echo "Failed to apply sysctl knobs. Skipping..." | |
# Increase session file limits only (ignore systemd settings) | |
echo "Increasing session file limits..." | |
sudo bash -c "cat > $LIMITS_CONF_FILE <<EOF | |
# Increase process file descriptor count limit | |
* soft nofile 1000000 | |
* hard nofile 1000000 | |
EOF" || echo "Failed to increase session file limits. Skipping..." | |
# Optional: Building from Source | |
echo "Optional: Building from source..." | |
# Clone the repository or pull the latest changes | |
if [ ! -d "$GIT_DIR" ]; then | |
echo "Cloning the repository..." | |
git clone "$GIT_REPO" | |
else | |
echo "Repository directory already exists, pulling latest changes..." | |
cd "$GIT_DIR" || err "Failed to change directory to $GIT_DIR" | |
git pull | |
fi | |
# Switch to the xolana directory | |
echo "Switching to the xolana directory..." | |
cd "$GIT_DIR" || err "Failed to change directory to $GIT_DIR" | |
git checkout xolana || err "Failed to switch branch to 'xolana'" | |
echo "Current directory: $(pwd)" | |
# Check if Rust is already installed | |
echo "Checking for Rust installation..." | |
if ! command -v rustc &> /dev/null; then | |
echo "Rust is not installed, installing Rust..." | |
curl https://sh.rustup.rs -sSf | sh -s -- -y | |
source $HOME/.cargo/env | |
rustup component add rustfmt | |
rustup update | |
else | |
echo "Rust is already installed, skipping installation..." | |
fi | |
cargo build --release || err "Failed to build the project with cargo" | |
# Check version | |
echo "Checking Solana Validator version..." | |
./target/release/solana-validator -V || err "Failed to check Solana validator version" | |
# Create key-pairs if they don't already exist | |
echo "Creating key-pairs..." | |
# Check if files already exist and skip creating them if they do | |
if [ ! -f "$HOME/.config/solana/id.json" ]; then | |
echo "Creating $HOME/.config/solana/id.json..." | |
solana-keygen new --no-passphrase -o $HOME/.config/solana/id.json | |
else | |
echo "$HOME/.config/solana/id.json already exists, skipping creation..." | |
fi | |
if [ ! -f "identity.json" ]; then | |
echo "Creating identity.json..." | |
solana-keygen new --no-passphrase -o identity.json | |
else | |
echo "identity.json already exists, skipping creation..." | |
fi | |
if [ ! -f "vote.json" ]; then | |
echo "Creating vote.json..." | |
solana-keygen new --no-passphrase -o vote.json | |
else | |
echo "vote.json already exists, skipping creation..." | |
fi | |
if [ ! -f "withdrawer.json" ]; then | |
echo "Creating withdrawer.json..." | |
solana-keygen new --no-passphrase -o withdrawer.json | |
else | |
echo "withdrawer.json already exists, skipping creation..." | |
fi | |
if [ ! -f "stake.json" ]; then | |
echo "Creating stake.json..." | |
solana-keygen new --no-passphrase -o stake.json | |
else | |
echo "stake.json already exists, skipping creation..." | |
fi | |
# Airdrop using Xen Faucet API | |
echo "Configuring Solana and requesting airdrop via Xen faucet..." | |
solana config set -u https://xolana.xen.network | |
# Check if the keypair path is valid | |
if [ -f "$KEYPAIR_PATH" ]; then | |
echo "Keypair file found at $KEYPAIR_PATH" | |
else | |
echo "Keypair file not found at $KEYPAIR_PATH. Please ensure your Solana CLI is configured correctly." | |
exit 1 | |
fi | |
# Extract the public key from the keypair file | |
pubkey=$(solana-keygen pubkey "$KEYPAIR_PATH") | |
echo "Public key: $pubkey" | |
# Proceed with the rest of the script, such as requesting the airdrop | |
response=$(curl -X POST https://xolana.xen.network/faucet \ | |
-H "Content-Type: application/json" \ | |
-d "{\"pubkey\":\"$pubkey\"}") | |
echo "Airdrop response: $response" | |
# Transfer 1 SOL to identity account | |
echo "Transferring 1 SOL to identity account..." | |
solana transfer identity.json 1 --allow-unfunded-recipient | |
# Create Stake Account | |
echo "Creating stake account..." | |
if ! solana stake-account stake.json &>/dev/null; then | |
solana create-stake-account stake.json 3 | |
else | |
echo "Stake account already exists, skipping creation..." | |
fi | |
# Create Vote Account | |
echo "Creating vote account..." | |
if ! solana vote-account vote.json &>/dev/null; then | |
solana create-vote-account vote.json identity.json withdrawer.json --commission 10 | |
else | |
echo "Vote account already exists, skipping creation..." | |
fi | |
# Stake | |
echo "Staking SOL..." | |
solana transfer stake.json 1 || echo "Failed to transfer SOL, continuing..." | |
solana delegate-stake stake.json vote.json || echo "Failed to delegate stake, continuing..." | |
# Open necessary ports and enable the firewall | |
echo "Opening required ports and enabling the firewall..." | |
{ | |
sudo ufw allow 8000:10000/tcp || echo "Failed to allow TCP port range 8000-10000" | |
sudo ufw allow 8000:10000/udp || echo "Failed to allow port 8000:10000/udp" | |
} || true | |
# Enable and reload the firewall | |
echo "Enabling the firewall..." | |
sudo ufw enable || echo "Failed to enable the firewall, continuing..." | |
echo "Reloading firewall rules..." | |
sudo ufw reload || echo "Failed to reload firewall rules, continuing..." | |
echo "Checking firewall status..." | |
sudo ufw status verbose || echo "Failed to check firewall status, continuing..." | |
# Run Validator | |
echo "Running validator..." | |
if [ -f "./target/release/solana-validator" ]; then | |
nohup ./target/release/solana-validator \ | |
--identity identity.json \ | |
--limit-ledger-size 50000000 \ | |
--rpc-port 8899 \ | |
--entrypoint xolana.xen.network:8001 \ | |
--entrypoint 216.202.227.220:8001 \ | |
--full-rpc-api \ | |
--log - \ | |
--vote-account vote.json \ | |
--max-genesis-archive-unpacked-size 1073741824 \ | |
--no-incremental-snapshots \ | |
--maximum-snapshots-to-retain 5 \ | |
--snapshot-compression lz4 \ | |
--require-tower \ | |
--enable-rpc-transaction-history \ | |
--enable-extended-tx-metadata-storage \ | |
--skip-startup-ledger-verification & | |
else | |
echo "solana-validator binary not found in ./target/release/. Please ensure it is built correctly." | |
fi | |
sleep 100 # Give some time for the validator to start | |
# Check Catchup Status | |
echo "Checking catchup status..." | |
attempts=0 | |
while (( attempts < MAX_ATTEMPTS )); do | |
echo "Checking catchup status... (Attempt $((attempts+1))/$MAX_ATTEMPTS)" | |
CATCHUP_STATUS=$(solana catchup --our-localhost) | |
if echo "$CATCHUP_STATUS" | grep -q "has caught up"; then | |
echo "Validator has caught up with the network." | |
break | |
else | |
echo "Validator has not caught up. Retrying..." | |
sleep $CATCHUP_TIMEOUT | |
((attempts++)) | |
if (( attempts == MAX_ATTEMPTS )); then | |
echo "Validator failed to catch up. Stopping and restarting..." | |
pkill -f solana-validator | |
rm -rf $LEDGER_DIR # Delete ledger | |
nohup ./target/release/solana-validator \ | |
--identity identity.json \ | |
--limit-ledger-size 50000000 \ | |
--rpc-port 8899 \ | |
--entrypoint xolana.xen.network:8001 \ | |
--full-rpc-api \ | |
--log - \ | |
--vote-account vote.json \ | |
--max-genesis-archive-unpacked-size 1073741824 \ | |
--no-incremental-snapshots \ | |
--require-tower \ | |
--enable-rpc-transaction-history \ | |
--enable-extended-tx-metadata-storage \ | |
--skip-startup-ledger-verification \ & | |
fi | |
fi | |
done | |
# Check status | |
echo "Checking logs and validator status..." | |
tail -f nohup.out & | |
solana leader-schedule | grep identity.json | |
solana gossip | |
solana validators | |
solana block-production | |
solana epoch-info | |
# End script with validator still running | |
echo "Setup complete. Validator is running." | |
echo "To stop the validator, use 'pkill -f solana-validator'." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment