/ scripts / devnet.sh
devnet.sh
  1  #!/bin/bash
  2  
  3  if [[ -n "$TMUX" ]]; then
  4    echo "Detected nested tmux session. Try again after unsetting \$TMUX, e.g., using \`unset TMUX\` in bash."
  5    exit 1
  6  fi
  7  
  8  # Read the total number of validators from the user or use a default value of 4
  9  read -p "Enter the total number of validators (default: 4): " total_validators
 10  total_validators=${total_validators:-4}
 11  
 12  # Read the total number of clients from the user or use a default value of 2
 13  read -p "Enter the total number of clients (default: 2): " total_clients
 14  total_clients=${total_clients:-2}
 15  
 16  # Read the network ID from user or use a default value of 1
 17  read -p "Enter the network ID (mainnet = 0, testnet = 1, canary = 2) (default: 1): " network_id
 18  network_id=${network_id:-1}
 19  
 20  # Ask the user if they want to run 'cargo install --locked --path .' or use a pre-installed binary
 21  read -p "Do you want to run 'cargo install --locked --path .' to build the binary? (y/n, default: y): " build_binary
 22  build_binary=${build_binary:-y}
 23  
 24  # Ask the user whether to clear the existing ledger history
 25  read -p "Do you want to clear the existing ledger history? (y/n, default: n): " clear_ledger
 26  clear_ledger=${clear_ledger:-n}
 27  
 28  # Log verbosity is set to 1 (DEBUG) by default.
 29  verbosity=1
 30  
 31  # Binary path set to "" by default (using installed binary) 
 32  binary_path=""
 33  
 34  if [[ $build_binary == "y" ]]; then
 35    # Ask the user if they want to enable validator telemetry
 36    read -p "Do you want to enable validator telemetry? (y/n, default: y): " enable_telemetry
 37    enable_telemetry=${enable_telemetry:-y}
 38  
 39    # Ask the user for additional crate features (comma-separated)
 40    read -p "Enter crate features to enable (comma separated, default: test_network): " crate_features
 41    crate_features=${crate_features:-test_network}
 42  
 43    # Build command
 44    build_cmd="cargo install --locked --path ."
 45  
 46    # Add the telemetry feature if requested
 47    if [[ $enable_telemetry == "y" ]]; then
 48      build_cmd+=" --features telemetry"
 49    fi
 50  
 51    # Add any extra features if provided
 52    if [[ -n $crate_features ]]; then
 53      # If telemetry was also enabled, append with a comma separator
 54      if [[ $enable_telemetry == "y" ]]; then
 55        build_cmd+=",${crate_features}"
 56      else
 57        build_cmd+=" --features ${crate_features}"
 58      fi
 59    fi
 60  
 61    # Build command
 62    echo "Running build command: \"$build_cmd\""
 63    eval "$build_cmd" || exit 1
 64  else
 65    # Ask the user whether to use a custom relative path
 66    read -p "Do you want to run snarkos from a relative path? (e.g. ./target/debug/, defaults to the installed binary): " binary_path
 67    binary_path=${binary_path:-""}
 68  fi
 69  
 70  # Clear the ledger logs for each validator if the user chooses to clear ledger
 71  if [[ $clear_ledger == "y" ]]; then
 72    # Create an array to store background processes
 73    clean_processes=()
 74  
 75    for ((index = 0; index < $((total_validators + total_clients)); index++)); do
 76      # Run 'snarkos clean' for each node in the background
 77      "${binary_path}snarkos" clean "--network=$network_id" "--dev=$index" "--dev-num-validators=$total_validators" &
 78  
 79      # Store the process ID of the background task
 80      clean_processes+=($!)
 81    done
 82  
 83    # Wait for all 'snarkos clean' processes to finish
 84    for process_id in "${clean_processes[@]}"; do
 85      wait "$process_id"
 86    done
 87  fi
 88  
 89  # Create a timestamp-based directory for log files
 90  log_dir=".logs-$(date +"%Y%m%d%H%M%S")"
 91  mkdir -p "$log_dir"
 92  
 93  # Create a new tmux session named "devnet"
 94  tmux new-session -d -s "devnet" -n "validator-0"
 95  if [[ $? -ne 0 ]]; then
 96    echo "Failed to create new TMUX session."
 97    exit 1
 98  fi
 99  
100  # Get the tmux's base-index for windows
101  # we have to create all windows with index offset by this much
102  index_offset="$(tmux show-option -gv base-index)"
103  if [ -z "$index_offset" ]; then
104    index_offset=0
105  fi
106  
107  # Generate validator indices from 0 to (total_validators - 1)
108  validator_indices=($(seq 0 $((total_validators - 1))))
109  
110  # Loop through the list of validator indices and create a new window for each
111  for validator_index in "${validator_indices[@]}"; do
112    # Generate a unique and incrementing log file name based on the validator indexi
113    name="validator-$validator_index"
114    log_file="$log_dir/$name.log"
115    window_index=$((validator_index + index_offset))
116    metrics_port=$((validator_index + 9000))
117  
118    if [ "$validator_index" -ne 0 ]; then
119      # We don't need to create a window for the first validator because the tmux session already starts with one window.
120      tmux new-window -t "devnet:$window_index" -n $name
121    fi
122  
123    # Send the command to start the validator to the new window and capture output to the log file
124    tmux send-keys -t "devnet:$window_index" "${binary_path}snarkos start --dev-num-clients $total_clients --nodisplay --network $network_id --dev $validator_index --dev-num-validators $total_validators --validator --logfile $log_file --verbosity $verbosity --metrics --metrics-ip=0.0.0.0:$metrics_port --no-dev-txs" C-m
125  done
126  
127  if [ "$total_clients" -ne 0 ]; then
128    # Generate client indices from 0 to (total_clients - 1)
129    client_indices=($(seq 0 $((total_clients - 1))))
130  
131    # Loop through the list of client indices and create a new window for each
132    for client_index in "${client_indices[@]}"; do
133      # Generate a unique and incrementing log file name based on the client index
134      name="client-$client_index"
135      log_file="$log_dir/$name.log"
136  
137      window_index=$((client_index + total_validators + index_offset))
138  
139      # Create a new window with a unique name
140      tmux new-window -t "devnet:$window_index" -n $name
141  
142      # Send the command to start the client to the new window and capture output to the log file
143      tmux send-keys -t "devnet:$window_index" "${binary_path}snarkos start --nodisplay --network $network_id --dev $window_index --dev-num-validators $total_validators --client --logfile $log_file  --verbosity $verbosity" C-m
144    done
145  fi
146  
147  # Attach to the tmux session to view and interact with the windows
148  tmux attach-session -t "devnet"