|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +set -e |
| 4 | + |
| 5 | +# Variables |
| 6 | +USER="ubuntu" |
| 7 | +PASSWORD_FILE="/home/$USER/password.txt" |
| 8 | +SECRET_DIR="/home/$USER/.secrets" |
| 9 | +DATA_DIR="/home/$USER/data" |
| 10 | +LOG_DIR="/var/log" |
| 11 | + |
| 12 | +# Function to generate a random 25-character password |
| 13 | +generate_password() { |
| 14 | + mkdir -p $(dirname "$PASSWORD_FILE") |
| 15 | + cat /dev/urandom | tr -dc 'A-Za-z0-9' | head -c 25 > "$PASSWORD_FILE" |
| 16 | +} |
| 17 | + |
| 18 | +# Function to install Go 1.21 from source |
| 19 | +install_go() { |
| 20 | + # Check if Go is already installed |
| 21 | + if ! command -v go &> /dev/null && [ ! -d "/usr/local/go" ]; then |
| 22 | + echo "Go is not installed. Installing Go..." |
| 23 | + |
| 24 | + # Download the pre-compiled binary of Go 1.21 |
| 25 | + wget https://golang.org/dl/go1.21.0.linux-amd64.tar.gz |
| 26 | + sudo tar -xvf go1.21.0.linux-amd64.tar.gz |
| 27 | + sudo mv go /usr/local |
| 28 | + |
| 29 | + # Set environment variables so the system knows where to find Go |
| 30 | + echo "export GOROOT=/usr/local/go" | sudo tee /etc/profile.d/goenv.sh |
| 31 | + echo "export PATH=\$PATH:\$GOROOT/bin" | sudo tee -a /etc/profile.d/goenv.sh |
| 32 | + |
| 33 | + source /etc/profile.d/goenv.sh |
| 34 | + |
| 35 | + sudo ln -s /usr/local/go/bin/go /usr/local/bin/go |
| 36 | + else |
| 37 | + echo "Go is already installed. Skipping installation." |
| 38 | + fi |
| 39 | +} |
| 40 | + |
| 41 | + |
| 42 | + |
| 43 | +# Function to install Rust and Cargo |
| 44 | +install_rust() { |
| 45 | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y |
| 46 | + source "$HOME/.cargo/env" |
| 47 | +} |
| 48 | + |
| 49 | +# Function to clone and build repositories |
| 50 | +clone_and_build() { |
| 51 | + if [ ! -d "sugarfunge-api" ] || [ -z "$(ls -A sugarfunge-api)" ]; then |
| 52 | + git clone https://github.com/functionland/sugarfunge-api.git |
| 53 | + fi |
| 54 | + cd sugarfunge-api |
| 55 | + cargo build --release |
| 56 | + cd .. |
| 57 | + |
| 58 | + if [ ! -d "sugarfunge-node" ] || [ -z "$(ls -A sugarfunge-node)" ]; then |
| 59 | + git clone https://github.com/functionland/sugarfunge-node.git |
| 60 | + fi |
| 61 | + cd sugarfunge-node |
| 62 | + cargo build --release |
| 63 | + cd .. |
| 64 | + |
| 65 | + if [ ! -d "go-fula" ] || [ -z "$(ls -A go-fula)" ]; then |
| 66 | + git clone https://github.com/functionland/go-fula.git |
| 67 | + fi |
| 68 | + cd go-fula |
| 69 | + go build -o go-fula ./cmd/blox |
| 70 | + cd .. |
| 71 | +} |
| 72 | + |
| 73 | + |
| 74 | +# Function to set up and extract keys |
| 75 | +setup_and_extract_keys() { |
| 76 | + mkdir -p "$SECRET_DIR" |
| 77 | + if [ ! -f "$SECRET_DIR/secret_phrase.txt" ] || [ ! -f "$SECRET_DIR/secret_seed.txt" ]; then |
| 78 | + output=$(./sugarfunge-node/target/release/sugarfunge-node key generate --scheme Sr25519 --password-filename="$PASSWORD_FILE" 2>&1) |
| 79 | + echo "$output" |
| 80 | + secret_phrase=$(echo "$output" | grep "Secret phrase:" | awk '{$1=$2=""; print $0}' | sed 's/^[ \t]*//;s/[ \t]*$//') |
| 81 | + echo "$secret_phrase" > "$SECRET_DIR/secret_phrase.txt" |
| 82 | + |
| 83 | + secret_seed=$(echo "$output" | grep "Secret seed:" | awk '{$1=$2=""; print $0}' | sed 's/^[ \t]*//;s/[ \t]*$//') |
| 84 | + echo "$secret_seed" > "$SECRET_DIR/secret_seed.txt" |
| 85 | + |
| 86 | + account=$(echo "$output" | grep "SS58 Address:" | awk '{$1=$2=""; print $0}' | sed 's/^[ \t]*//;s/[ \t]*$//') |
| 87 | + echo "$account" > "$SECRET_DIR/account.txt" |
| 88 | + fi |
| 89 | + if [ ! -f "$SECRET_DIR/node_key.txt" ]; then |
| 90 | + output=$(./sugarfunge-node/target/release/sugarfunge-node key generate-node-key 2>&1) |
| 91 | + echo "$output" |
| 92 | + node_key=$(echo "$output" | tr ' ' '\n' | tail -n 1) |
| 93 | + echo "$node_key" > "$SECRET_DIR/node_key.txt" |
| 94 | + |
| 95 | + node_peerid=$(echo "$output" | head -n 1) |
| 96 | + echo "$node_peerid" > "$SECRET_DIR/node_peerid.txt" |
| 97 | + fi |
| 98 | +} |
| 99 | + |
| 100 | +# Function to insert keys into the node |
| 101 | +insert_keys() { |
| 102 | + secret_phrase=$(cat "$SECRET_DIR/secret_phrase.txt") |
| 103 | + ./sugarfunge-node/target/release/sugarfunge-node key insert --base-path="$DATA_DIR" --chain ./customSpecRaw.json --scheme Sr25519 --suri "$secret_phrase" --password-filename "$PASSWORD_FILE" --key-type aura |
| 104 | + ./sugarfunge-node/target/release/sugarfunge-node key insert --base-path="$DATA_DIR" --chain ./customSpecRaw.json --scheme Ed25519 --suri "$secret_phrase" --password-filename "$PASSWORD_FILE" --key-type gran |
| 105 | +} |
| 106 | + |
| 107 | +# Function to set up and start node service |
| 108 | +setup_node_service() { |
| 109 | + sudo bash -c 'cat > /etc/systemd/system/sugarfunge-node.service' << EOF |
| 110 | +[Unit] |
| 111 | +Description=Sugarfunge Node |
| 112 | +After=network.target |
| 113 | +
|
| 114 | +[Service] |
| 115 | +Type=simple |
| 116 | +User=$USER |
| 117 | +ExecStart=$HOME/sugarfunge-node/target/release/sugarfunge-node \ |
| 118 | + --chain $HOME/sugarfunge-node/customSpecRaw.json \ |
| 119 | + --enable-offchain-indexing true \ |
| 120 | + --base-path="$DATA_DIR" \ |
| 121 | + --keystore-path="$SECRET_DIR" \ |
| 122 | + --port 30334 \ |
| 123 | + --rpc-port 9944 \ |
| 124 | + --rpc-cors=all \ |
| 125 | + --rpc-methods=Unsafe \ |
| 126 | + --rpc-external \ |
| 127 | + --validator \ |
| 128 | + --name MyNode \ |
| 129 | + --password-filename="$PASSWORD_FILE" \ |
| 130 | + --node-key=$(cat "$SECRET_DIR/node_key.txt") |
| 131 | +Restart=always |
| 132 | +StandardOutput=file:"$LOG_DIR/MyNode.log" |
| 133 | +StandardError=file:"$LOG_DIR/MyNode.err" |
| 134 | +
|
| 135 | +[Install] |
| 136 | +WantedBy=multi-user.target |
| 137 | +EOF |
| 138 | + |
| 139 | + sudo systemctl daemon-reload |
| 140 | + sudo systemctl enable sugarfunge-node.service |
| 141 | + sudo systemctl start sugarfunge-node.service |
| 142 | +} |
| 143 | + |
| 144 | + |
| 145 | +# Function to set up and start API service |
| 146 | +setup_api_service() { |
| 147 | + sudo bash -c 'cat > /etc/systemd/system/sugarfunge-api.service' << EOF |
| 148 | +[Unit] |
| 149 | +Description=Sugarfunge API |
| 150 | +After=sugarfunge-node.service |
| 151 | +Requires=sugarfunge-node.service |
| 152 | +
|
| 153 | +[Service] |
| 154 | +Type=simple |
| 155 | +User=$USER |
| 156 | +ExecStart=$HOME/sugarfunge-api/target/release/sugarfunge-api \ |
| 157 | + --db-uri="$DATA_DIR" \ |
| 158 | + --node-server ws://127.0.0.1:9946 |
| 159 | +Environment=FULA_SUGARFUNGE_API_HOST=http://127.0.0.1:4000 \ |
| 160 | + FULA_CONTRACT_API_HOST=https://contract-api.functionyard.fula.network \ |
| 161 | + LABOR_TOKEN_CLASS_ID=100 \ |
| 162 | + LABOR_TOKEN_ASSET_ID=100 \ |
| 163 | + CHALLENGE_TOKEN_CLASS_ID=110 \ |
| 164 | + CHALLENGE_TOKEN_ASSET_ID=100 \ |
| 165 | + LABOR_TOKEN_VALUE=1 \ |
| 166 | + CHALLENGE_TOKEN_VALUE=1 \ |
| 167 | + CLAIMED_TOKEN_CLASS_ID=120 \ |
| 168 | + CLAIMED_TOKEN_ASSET_ID=100 |
| 169 | +Restart=always |
| 170 | +StandardOutput=file:"$LOG_DIR/MyNodeAPI.log" |
| 171 | +StandardError=file:"$LOG_DIR/MyNodeAPI.err" |
| 172 | +
|
| 173 | +[Install] |
| 174 | +WantedBy=multi-user.target |
| 175 | +EOF |
| 176 | + |
| 177 | + sudo systemctl daemon-reload |
| 178 | + sudo systemctl enable sugarfunge-api.service |
| 179 | + sudo systemctl start sugarfunge-api.service |
| 180 | +} |
| 181 | + |
| 182 | + |
| 183 | +# Function to set up and start go-fula service |
| 184 | +setup_gofula_service() { |
| 185 | + sudo bash -c 'cat > /etc/systemd/system/go-fula.service' << EOF |
| 186 | +[Unit] |
| 187 | +Description=Go Fula Service |
| 188 | +After=network.target |
| 189 | +
|
| 190 | +[Service] |
| 191 | +Type=simple |
| 192 | +ExecStart=/home/$USER/go-fula/go-fula |
| 193 | +Restart=always |
| 194 | +
|
| 195 | +[Install] |
| 196 | +WantedBy=multi-user.target |
| 197 | +EOF |
| 198 | + |
| 199 | + sudo systemctl daemon-reload |
| 200 | + sudo systemctl enable go-fula.service |
| 201 | + sudo systemctl start go-fula.service |
| 202 | +} |
| 203 | + |
| 204 | +# Function to fund an account |
| 205 | +fund_account() { |
| 206 | + secret_seed=$(cat "$SECRET_DIR/secret_seed.txt") |
| 207 | + account=$(cat "$SECRET_DIR/account.txt") |
| 208 | + curl -X POST https://api.node3.functionyard.fula.network/account/fund \ |
| 209 | + -H "Content-Type: application/json" \ |
| 210 | + -d "{\"seed\": \"$secret_seed\", \"amount\": 1000000000000000000, \"to\": \"$account\"}" |
| 211 | +} |
| 212 | + |
| 213 | +# Function to create a pool |
| 214 | +create_pool() { |
| 215 | + seed=$(cat "$SECRET_DIR/secret_seed.txt") |
| 216 | + node_peerid=$(cat "$SECRET_DIR/node_peerid.txt") |
| 217 | + pool_name=$1 |
| 218 | + region=$2 |
| 219 | + |
| 220 | + response=$(curl -X POST https://api.node3.functionyard.fula.network/fula/pool/create \ |
| 221 | + -H "Content-Type: application/json" \ |
| 222 | + -d "{\"seed\": \"$seed\", \"pool_name\": \"$pool_name\", \"peer_id\": \"$node_peerid\", \"region\": \"$region\"}") |
| 223 | + |
| 224 | + pool_id=$(echo $response | jq '.pool_id') |
| 225 | + echo "Pool ID: $pool_id" |
| 226 | + |
| 227 | + # Update the Fula config file with the pool ID |
| 228 | + setup_fula_config "$pool_id" |
| 229 | +} |
| 230 | + |
| 231 | +# Function to setup the Fula config file |
| 232 | +setup_fula_config() { |
| 233 | + pool_id="$1" |
| 234 | + mkdir -p /home/$USER/.fula/blox/store |
| 235 | + cat > /home/$USER/.fula/config.yaml << EOF |
| 236 | +identity: |
| 237 | +storeDir: /home/$USER/.fula/blox/store |
| 238 | +poolName: "$pool_id" |
| 239 | +logLevel: info |
| 240 | +listenAddrs: |
| 241 | + - /ip4/0.0.0.0/tcp/40001 |
| 242 | + - /ip4/0.0.0.0/udp/40001/quic |
| 243 | + - /ip4/0.0.0.0/udp/40001/quic-v1 |
| 244 | + - /ip4/0.0.0.0/udp/40001/quic-v1/webtransport |
| 245 | +authorizer: 12D3KooWMMt4C3FKui14ai4r1VWwznRw6DoP5DcgTfzx2D5VZoWx |
| 246 | +authorizedPeers: |
| 247 | + - 12D3KooWMMt4C3FKui14ai4r1VWwznRw6DoP5DcgTfzx2D5VZoWx |
| 248 | +staticRelays: |
| 249 | + - /dns/relay.dev.fx.land/tcp/4001/p2p/12D3KooWDRrBaAfPwsGJivBoUw5fE7ZpDiyfUjqgiURq2DEcL835 |
| 250 | + - /dns/alpha-relay.dev.fx.land/tcp/4001/p2p/12D3KooWFLhr8j6LTF7QV1oGCn3DVNTs1eMz2u4KCDX6Hw3BFyag |
| 251 | + - /dns/bravo-relay.dev.fx.land/tcp/4001/p2p/12D3KooWA2JrcPi2Z6i2U8H3PLQhLYacx6Uj9MgexEsMsyX6Fno7 |
| 252 | + - /dns/charlie-relay.dev.fx.land/tcp/4001/p2p/12D3KooWKaK6xRJwjhq6u6yy4Mw2YizyVnKxptoT9yXMn3twgYns |
| 253 | + - /dns/delta-relay.dev.fx.land/tcp/4001/p2p/12D3KooWDtA7kecHAGEB8XYEKHBUTt8GsRfMen1yMs7V85vrpMzC |
| 254 | + - /dns/echo-relay.dev.fx.land/tcp/4001/p2p/12D3KooWQBigsW1tvGmZQet8t5MLMaQnDJKXAP2JNh7d1shk2fb2 |
| 255 | +forceReachabilityPrivate: true |
| 256 | +allowTransientConnection: true |
| 257 | +disableResourceManger: true |
| 258 | +maxCIDPushRate: 100 |
| 259 | +ipniPublishDisabled: true |
| 260 | +ipniPublishInterval: 10s |
| 261 | +IpniPublishDirectAnnounce: |
| 262 | + - https://cid.contact/ingest/announce |
| 263 | +ipniPublisherIdentity: |
| 264 | +EOF |
| 265 | +} |
| 266 | + |
| 267 | +cleanup() { |
| 268 | + echo "Cleaning up..." |
| 269 | + |
| 270 | + # Remove Go tarball |
| 271 | + if [ -f "go1.21.0.linux-amd64.tar.gz" ]; then |
| 272 | + echo "Removing Go tarball..." |
| 273 | + rm go1.21.0.linux-amd64.tar.gz |
| 274 | + fi |
| 275 | + |
| 276 | + # Add other cleanup tasks here |
| 277 | +} |
| 278 | + |
| 279 | +# Main script execution |
| 280 | +main() { |
| 281 | + # Check if a region is provided |
| 282 | + if [ $# -lt 1 ]; then |
| 283 | + echo "Please provide a region as an argument." |
| 284 | + exit 1 |
| 285 | + fi |
| 286 | + |
| 287 | + region=$1 |
| 288 | + pool_name="${region// /}" |
| 289 | + |
| 290 | + # Update and install dependencies |
| 291 | + sudo apt update |
| 292 | + sudo apt install -y wget git curl build-essential jq pkg-config libssl-dev |
| 293 | + |
| 294 | + # Install Go 1.21 from source |
| 295 | + install_go |
| 296 | + |
| 297 | + # Install Rust and Cargo |
| 298 | + install_rust |
| 299 | + |
| 300 | + # Clone and build the necessary repositories |
| 301 | + clone_and_build |
| 302 | + |
| 303 | + # Generate a strong password and save it |
| 304 | + generate_password |
| 305 | + |
| 306 | + # Setup and extract keys |
| 307 | + setup_and_extract_keys |
| 308 | + |
| 309 | + # Insert keys into the node |
| 310 | + insert_keys |
| 311 | + |
| 312 | + # Setup and start node service |
| 313 | + setup_node_service |
| 314 | + |
| 315 | + # Setup and start API service |
| 316 | + setup_api_service |
| 317 | + |
| 318 | + # Setup and start go-fula service |
| 319 | + setup_gofula_service |
| 320 | + |
| 321 | + # Fund an account |
| 322 | + fund_account |
| 323 | + |
| 324 | + # Create a pool |
| 325 | + create_pool "$pool_name" "$region" |
| 326 | + |
| 327 | + cleanup |
| 328 | + |
| 329 | + echo "Setup complete. Please review the logs and verify the services are running correctly." |
| 330 | +} |
| 331 | + |
| 332 | +# Run the main function with the provided region |
| 333 | +main "$@" |
0 commit comments