From 84a8f719967ed1550e0c8e3eccaf64cb93b36982 Mon Sep 17 00:00:00 2001 From: h3rt Date: Fri, 25 Oct 2024 02:47:29 +0200 Subject: [PATCH 1/5] Fix and update Run Node Script --- scripts/run-node.py | 140 +++++++++++++++++++++++++++++--------------- 1 file changed, 92 insertions(+), 48 deletions(-) diff --git a/scripts/run-node.py b/scripts/run-node.py index f222a3edfc..03f1118f5a 100644 --- a/scripts/run-node.py +++ b/scripts/run-node.py @@ -8,21 +8,22 @@ import requests import json import zipfile +import hashlib +import math from io import BytesIO # Set up logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') # Advanced user configs -moniker = "pynode" # Custom moniker for the node -trust_height_delta = 20000 # Negative height offset for state sync -enable_unsafe_reset = True # Wipe database and keys before setup +moniker = "seinode" # Custom moniker for the node +trust_height_delta = 100000 # Negative height offset for state sync version_override = False # Override version fetching. if true, specify version(s) below # Chain binary version ["version_override" must be true to use] -MAINNET_VERSION = "v3.9.0" -DEVNET_VERSION = "v5.2.2" -TESTNET_VERSION = "v5.2.2" +MAINNET_VERSION = "v5.9.0-hotfix" +DEVNET_VERSION = "v5.9.0-hotfix" +TESTNET_VERSION = "v5.9.0-hotfix" # Map env to chain ID and optional manual version override ENV_TO_CONFIG = { @@ -56,12 +57,7 @@ def print_ascii_and_intro(): Welcome to the Sei node installer! For more information please visit docs.sei.io -Please make sure you have the following installed locally: -\t- golang 1.21 (with PATH and GOPATH set properly) -\t- make -\t- gcc -\t- docker -This tool will build from scratch seid and wipe away existing state. +This tool will download the seid binary from sei-binaries and wipe any existing state. Please backup any important existing data before proceeding. """) @@ -131,34 +127,72 @@ def fetch_latest_version(): logging.error(f"Failed to fetch latest version from GitHub API: {e}") sys.exit(1) -# Install release based on version tag. +def compute_sha256(file_path): + sha256 = hashlib.sha256() + with open(file_path, "rb") as f: + for chunk in iter(lambda: f.read(4096), b""): + sha256.update(chunk) + return sha256.hexdigest() + def install_release(version): try: - zip_url = f"https://github.com/sei-protocol/sei-chain/archive/refs/tags/{version}.zip" - response = requests.get(zip_url) - response.raise_for_status() - zip_file = zipfile.ZipFile(BytesIO(response.content)) - zip_file.extractall(".") + base_url = f"https://github.com/alexander-sei/sei-binaries/releases/download/{version}/" + tag = f"seid-{version}-linux-amd64" + binary_url = f"{base_url}{tag}" + sha256_url = f"{base_url}{tag}.sha256" + install_dir = "/usr/local/bin" + binary_path = os.path.join(install_dir, "seid") + + logging.info(f"Downloading binary from {binary_url}") + binary_response = requests.get(binary_url) + binary_response.raise_for_status() + + logging.info(f"Downloading SHA256 checksum from {sha256_url}") + sha256_response = requests.get(sha256_url) + sha256_response.raise_for_status() + + # Extract the SHA256 hash from the .sha256 file + sha256_hash = sha256_response.text.strip().split()[0] + logging.info(f"Expected SHA256 hash: {sha256_hash}") + + # Save the binary to a temporary file + temp_binary_path = "/tmp/seid-binary" + with open(temp_binary_path, "wb") as binary_file: + binary_file.write(binary_response.content) + + # Compute the SHA256 hash of the downloaded binary + logging.info(f"Computing SHA256 hash of the binary at {temp_binary_path}") + sha256_computed = compute_sha256(temp_binary_path) + logging.info(f"Computed SHA256 hash: {sha256_computed}") + + # Compare the computed hash with the expected hash + if sha256_computed != sha256_hash: + raise ValueError("SHA256 hash mismatch! The binary may be corrupted or tampered with.") + else: + logging.info("SHA256 hash verification passed.") - os.chdir(zip_file.namelist()[0]) - subprocess.run(["make", "install"], check=True) - logging.info(f"Successfully installed version: {version}") + # Move the binary to the install directory and rename it to 'seid' + logging.info(f"Moving binary to {binary_path}") + subprocess.run(["sudo", "mv", temp_binary_path, binary_path], check=True) - except requests.exceptions.HTTPError as e: - logging.error(f"HTTP error occurred: {e}") # Handle http error - sys.exit(1) - except requests.exceptions.RequestException as e: - logging.error(f"Error downloading files: {e}") # Handle other errors - sys.exit(1) - except zipfile.BadZipFile: - logging.error("Error unzipping file. The downloaded file may be corrupt.") - sys.exit(1) - except subprocess.CalledProcessError as e: - logging.error(f"Installation failed during 'make install': {e}") - sys.exit(1) - except Exception as e: - logging.error(f"An unexpected error occurred: {e}") - sys.exit(1) + # Make the binary executable + logging.info(f"Setting executable permissions for {binary_path}") + subprocess.run(["sudo", "chmod", "+x", binary_path], check=True) + + logging.info(f"Successfully installed 'seid' version: {version} to {binary_path}") + + except requests.HTTPError as http_err: + logging.error(f"HTTP error occurred: {http_err}") + except Exception as err: + logging.error(f"An error occurred: {err}") + +def compute_sha256(file_path, chunk_size=8192): + """Compute the SHA256 hash of a file.""" + sha256 = hashlib.sha256() + with open(file_path, "rb") as f: + for chunk in iter(lambda: f.read(chunk_size), b""): + sha256.update(chunk) + return sha256.hexdigest() # Fetch version from RPC unless "version_override = true" def fetch_node_version(rpc_url): @@ -177,13 +211,26 @@ def fetch_node_version(rpc_url): return None # Fetch state sync params -def get_state_sync_params(rpc_url): +def get_state_sync_params(rpc_url, trust_height_delta, chain_id): response = requests.get(f"{rpc_url}/status") latest_height = int(response.json()['sync_info']['latest_block_height']) + + # Calculate sync block height sync_block_height = latest_height - trust_height_delta if latest_height > trust_height_delta else latest_height - response = requests.get(f"{rpc_url}/block?height={sync_block_height}") + + # Determine the rounding based on the chain_id + if chain_id.lower() == 'pacific-1': + # Round sync block height to the next 100,000 for mainnet + rounded_sync_block_height = math.ceil(sync_block_height / 100000) * 100000 + 2 + else: + # Round sync block height to the next 2,000 for devnet or testnet + rounded_sync_block_height = math.ceil(sync_block_height / 2000) * 2000 + 2 + + # Fetch block hash + response = requests.get(f"{rpc_url}/block?height={rounded_sync_block_height}") sync_block_hash = response.json()['block_id']['hash'] - return sync_block_height, sync_block_hash + + return rounded_sync_block_height, sync_block_hash # Fetch peers list def get_persistent_peers(rpc_url): @@ -249,14 +296,7 @@ def main(): # Install selected release install_release(version) - # Unsafe-reset-all only if directory exists, and by config at top of script home_dir = os.path.expanduser('~/.sei') - if enable_unsafe_reset and os.path.exists(home_dir): - try: - subprocess.run(["seid", "tendermint", "unsafe-reset-all"], check=True) - except subprocess.CalledProcessError as e: - logging.error(f"Failed to execute 'seid tendermint unsafe-reset-all': {e}") - sys.exit(1) # Clean up previous data, init seid with given chain ID and moniker subprocess.run(["rm", "-rf", home_dir]) @@ -269,7 +309,7 @@ def main(): run_command(local_script_path) else: # Fetch state-sync params and persistent peers - sync_block_height, sync_block_hash = get_state_sync_params(rpc_url) + sync_block_height, sync_block_hash = get_state_sync_params(rpc_url, trust_height_delta,chain_id) persistent_peers = get_persistent_peers(rpc_url) # Fetch and write genesis @@ -292,7 +332,11 @@ def main(): config_data = config_data.replace('persistent-peers = ""', f'persistent-peers = "{persistent_peers}"') config_data = config_data.replace('enable = false', 'enable = true') config_data = config_data.replace('db-sync-enable = true', 'db-sync-enable = false') - config_data = config_data.replace('use-p2p = false', 'use-p2p = true') + config_data = config_data.replace('fetchers = "4"', 'fetchers = "2"') + config_data = config_data.replace('send-rate = 20480000', 'send-rate = 20480000000000') + config_data = config_data.replace('recv-rate = 20480000', 'recv-rate = 20480000000000') + config_data = config_data.replace('chunk-request-timeout = "15s"', 'chunk-request-timeout = "10s"') + with open(config_path, 'w') as file: file.write(config_data) From 799c62b44a9e8ee3fba75387efda0b6abcb44544 Mon Sep 17 00:00:00 2001 From: h3rt Date: Sat, 26 Oct 2024 00:24:35 +0200 Subject: [PATCH 2/5] Add custom ports, extra compilation for local nodes, clean up --- scripts/run-node.py | 127 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 106 insertions(+), 21 deletions(-) diff --git a/scripts/run-node.py b/scripts/run-node.py index 03f1118f5a..1ab9762ef2 100644 --- a/scripts/run-node.py +++ b/scripts/run-node.py @@ -19,6 +19,12 @@ moniker = "seinode" # Custom moniker for the node trust_height_delta = 100000 # Negative height offset for state sync version_override = False # Override version fetching. if true, specify version(s) below +p2p_port = 26656 +rpc_port = 26657 +lcd_port = 1317 +grpc_port = 9090 +grpc_web_port = 9091 +pprof_port = 6060 # Chain binary version ["version_override" must be true to use] MAINNET_VERSION = "v5.9.0-hotfix" @@ -77,6 +83,7 @@ def take_manual_inputs(): env = input("Choose an environment: ") env = ["local", "devnet", "testnet", "mainnet"][int(env) - 1] + db_choice = input("Choose the database backend (1: legacy [default], 2: sei-db): ").strip() or "1" if db_choice not in ["1", "2"]: db_choice = "1" # Default to "1" if the input is invalid or empty @@ -127,6 +134,7 @@ def fetch_latest_version(): logging.error(f"Failed to fetch latest version from GitHub API: {e}") sys.exit(1) +# Computes the sha256 hash of a file def compute_sha256(file_path): sha256 = hashlib.sha256() with open(file_path, "rb") as f: @@ -134,6 +142,77 @@ def compute_sha256(file_path): sha256.update(chunk) return sha256.hexdigest() +# Compile and install release based on version tag +def compile_and_install_release(version): + logging.info(f"Starting compilation and installation for version: {version}") + try: + zip_url = f"https://github.com/sei-protocol/sei-chain/archive/refs/tags/{version}.zip" + logging.info(f"Constructed zip URL: {zip_url}") + + logging.info("Initiating download of the release zip file...") + response = requests.get(zip_url, timeout=30) + response.raise_for_status() + logging.info("Download completed successfully.") + + logging.info("Extracting the zip file...") + zip_file = zipfile.ZipFile(BytesIO(response.content)) + zip_file.extractall(".") + logging.info("Extraction completed.") + + # Get the name of the extracted directory + extracted_dir = zip_file.namelist()[0].rstrip('/') + logging.info(f"Extracted directory: {extracted_dir}") + + # Define the new directory name + new_dir_name = "sei-chain" + + # Check if the new directory name already exists + if os.path.exists(new_dir_name): + logging.error(f"The directory '{new_dir_name}' already exists. It will be removed.") + sys.exit(1) + + # Rename the extracted directory to 'sei-chain' + logging.info(f"Renaming '{extracted_dir}' to '{new_dir_name}'") + os.rename(extracted_dir, new_dir_name) + logging.info(f"Renaming completed.") + + # Change directory to the new directory + os.chdir(new_dir_name) + logging.info(f"Changed working directory to '{new_dir_name}'") + + logging.info("Starting the 'make install' process...") + result = subprocess.run( + ["make", "install"], + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True + ) + logging.info("Make install completed successfully.") + logging.debug(f"Make install stdout: {result.stdout}") + logging.debug(f"Make install stderr: {result.stderr}") + + logging.info(f"Successfully installed version: {version}") + logging.info(f"Output from make install:\n{result.stdout}") + + except requests.exceptions.HTTPError as e: + logging.error(f"HTTP error occurred: {e}") + sys.exit(1) + except requests.exceptions.RequestException as e: + logging.error(f"Error downloading files: {e}") + sys.exit(1) + except zipfile.BadZipFile: + logging.error("Error unzipping file. The downloaded file may be corrupt.") + sys.exit(1) + except subprocess.CalledProcessError as e: + # Display the output and error from the make command if it fails + logging.error(f"Installation failed during 'make install': {e}") + logging.error(f"Error output: {e.stderr}") + sys.exit(1) + except Exception as e: + logging.error(f"An unexpected error occurred: {e}") + sys.exit(1) + def install_release(version): try: base_url = f"https://github.com/alexander-sei/sei-binaries/releases/download/{version}/" @@ -186,14 +265,6 @@ def install_release(version): except Exception as err: logging.error(f"An error occurred: {err}") -def compute_sha256(file_path, chunk_size=8192): - """Compute the SHA256 hash of a file.""" - sha256 = hashlib.sha256() - with open(file_path, "rb") as f: - for chunk in iter(lambda: f.read(chunk_size), b""): - sha256.update(chunk) - return sha256.hexdigest() - # Fetch version from RPC unless "version_override = true" def fetch_node_version(rpc_url): if not version_override: @@ -293,21 +364,28 @@ def main(): dynamic_version = fetch_node_version(rpc_url) if not version_override else None version = dynamic_version or version # Use the fetched version if not overridden - # Install selected release - install_release(version) - home_dir = os.path.expanduser('~/.sei') - # Clean up previous data, init seid with given chain ID and moniker - subprocess.run(["rm", "-rf", home_dir]) - subprocess.run(["seid", "init", moniker, "--chain-id", chain_id], check=True) - if env == "local": + # Clean up previous data, init seid with given chain ID and moniker + compile_and_install_release(version) + + subprocess.run(["rm", "-rf", home_dir]) + subprocess.run(["seid", "init", moniker, "--chain-id", chain_id], check=True) + logging.info("Running local initialization script...") local_script_path = os.path.expanduser('~/sei-chain/scripts/initialize_local_chain.sh') run_command(f"chmod +x {local_script_path}") run_command(local_script_path) + else: + # Install selected release + install_release(version) + + # Clean up previous data, init seid with given chain ID and moniker + subprocess.run(["rm", "-rf", home_dir]) + subprocess.run(["seid", "init", moniker, "--chain-id", chain_id], check=True) + # Fetch state-sync params and persistent peers sync_block_height, sync_block_hash = get_state_sync_params(rpc_url, trust_height_delta,chain_id) persistent_peers = get_persistent_peers(rpc_url) @@ -336,16 +414,23 @@ def main(): config_data = config_data.replace('send-rate = 20480000', 'send-rate = 20480000000000') config_data = config_data.replace('recv-rate = 20480000', 'recv-rate = 20480000000000') config_data = config_data.replace('chunk-request-timeout = "15s"', 'chunk-request-timeout = "10s"') + config_data = config_data.replace('laddr = "tcp://127.0.0.1:26657"', f'laddr = "tcp://127.0.0.1:{rpc_port}"') + config_data = config_data.replace('laddr = "tcp://0.0.0.0:26656"', f'laddr = "tcp://0.0.0.0:{p2p_port}"') + config_data = config_data.replace('pprof-laddr = "localhost:6060"', f'pprof-laddr = "localhost:{pprof_port}"') with open(config_path, 'w') as file: file.write(config_data) + + # Read and modify app.toml + with open(app_config_path, 'r') as file: + app_data = file.read() + app_data = app_data.replace('address = "tcp://0.0.0.0:1317"', f'address = "tcp://0.0.0.0:{lcd_port}"') + app_data = app_data.replace('address = "0.0.0.0:9090"', f'address = "0.0.0.0:{grpc_port}"') + app_data = app_data.replace('address = "0.0.0.0:9091"', f'address = "0.0.0.0:{grpc_web_port}"') + if db_choice == "2": + app_data = app_data.replace('sc-enable = false', 'sc-enable = true') + app_data = app_data.replace('ss-enable = false', 'ss-enable = true') - # Read modify and write app.toml if sei-db is selected - if db_choice == "2": - with open(app_config_path, 'r') as file: - app_data = file.read() - app_data = app_data.replace('sc-enable = false', 'sc-enable = true') - app_data = app_data.replace('ss-enable = false', 'ss-enable = true') with open(app_config_path, 'w') as file: file.write(app_data) From 9cbadd072543e069228fa8bf573d5bb814de0ba3 Mon Sep 17 00:00:00 2001 From: alexander-sei Date: Thu, 31 Oct 2024 16:59:52 +0100 Subject: [PATCH 3/5] run-node script: use seidb as default --- scripts/run-node.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/run-node.py b/scripts/run-node.py index 1ab9762ef2..b01078bdf4 100644 --- a/scripts/run-node.py +++ b/scripts/run-node.py @@ -84,7 +84,7 @@ def take_manual_inputs(): env = ["local", "devnet", "testnet", "mainnet"][int(env) - 1] - db_choice = input("Choose the database backend (1: legacy [default], 2: sei-db): ").strip() or "1" + db_choice = input("Choose the database backend (1: sei-db [default], 2: legacy): ").strip() or "1" if db_choice not in ["1", "2"]: db_choice = "1" # Default to "1" if the input is invalid or empty return env, db_choice @@ -291,10 +291,10 @@ def get_state_sync_params(rpc_url, trust_height_delta, chain_id): # Determine the rounding based on the chain_id if chain_id.lower() == 'pacific-1': - # Round sync block height to the next 100,000 for mainnet + # Round sync block height to the next 100,000 + add 2 for mainnet rounded_sync_block_height = math.ceil(sync_block_height / 100000) * 100000 + 2 else: - # Round sync block height to the next 2,000 for devnet or testnet + # Round sync block height to the next 2,000 + add 2 for devnet or testnet rounded_sync_block_height = math.ceil(sync_block_height / 2000) * 2000 + 2 # Fetch block hash @@ -427,7 +427,7 @@ def main(): app_data = app_data.replace('address = "tcp://0.0.0.0:1317"', f'address = "tcp://0.0.0.0:{lcd_port}"') app_data = app_data.replace('address = "0.0.0.0:9090"', f'address = "0.0.0.0:{grpc_port}"') app_data = app_data.replace('address = "0.0.0.0:9091"', f'address = "0.0.0.0:{grpc_web_port}"') - if db_choice == "2": + if db_choice == "1": app_data = app_data.replace('sc-enable = false', 'sc-enable = true') app_data = app_data.replace('ss-enable = false', 'ss-enable = true') From ca2dfc71684c160537319ce9268e249b8036e867 Mon Sep 17 00:00:00 2001 From: alexander-sei Date: Fri, 1 Nov 2024 15:18:16 +0100 Subject: [PATCH 4/5] Sei-DB per default for run-node and improve run-sha256sum --- scripts/run-node.py | 11 ++++++----- scripts/run-sha256sum.sh | 35 +++++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/scripts/run-node.py b/scripts/run-node.py index b01078bdf4..48ec56992d 100644 --- a/scripts/run-node.py +++ b/scripts/run-node.py @@ -17,7 +17,7 @@ # Advanced user configs moniker = "seinode" # Custom moniker for the node -trust_height_delta = 100000 # Negative height offset for state sync +trust_height_delta = 0 # Negative height offset for state sync version_override = False # Override version fetching. if true, specify version(s) below p2p_port = 26656 rpc_port = 26657 @@ -28,8 +28,8 @@ # Chain binary version ["version_override" must be true to use] MAINNET_VERSION = "v5.9.0-hotfix" -DEVNET_VERSION = "v5.9.0-hotfix" TESTNET_VERSION = "v5.9.0-hotfix" +DEVNET_VERSION = "v5.9.0-hotfix" # Map env to chain ID and optional manual version override ENV_TO_CONFIG = { @@ -292,10 +292,10 @@ def get_state_sync_params(rpc_url, trust_height_delta, chain_id): # Determine the rounding based on the chain_id if chain_id.lower() == 'pacific-1': # Round sync block height to the next 100,000 + add 2 for mainnet - rounded_sync_block_height = math.ceil(sync_block_height / 100000) * 100000 + 2 + rounded_sync_block_height = math.floor(sync_block_height / 100000) * 100000 + 2 else: # Round sync block height to the next 2,000 + add 2 for devnet or testnet - rounded_sync_block_height = math.ceil(sync_block_height / 2000) * 2000 + 2 + rounded_sync_block_height = math.floor(sync_block_height / 2000) * 2000 + 2 # Fetch block hash response = requests.get(f"{rpc_url}/block?height={rounded_sync_block_height}") @@ -385,9 +385,10 @@ def main(): # Clean up previous data, init seid with given chain ID and moniker subprocess.run(["rm", "-rf", home_dir]) subprocess.run(["seid", "init", moniker, "--chain-id", chain_id], check=True) + subprocess.run(["sudo", "mount", "-t", "tmpfs", "-o", "size=12G,mode=1777", "overflow", "/tmp"], check=True) # Fetch state-sync params and persistent peers - sync_block_height, sync_block_hash = get_state_sync_params(rpc_url, trust_height_delta,chain_id) + sync_block_height, sync_block_hash = get_state_sync_params(rpc_url, trust_height_delta, chain_id) persistent_peers = get_persistent_peers(rpc_url) # Fetch and write genesis diff --git a/scripts/run-sha256sum.sh b/scripts/run-sha256sum.sh index f14b333f6a..77c529653a 100755 --- a/scripts/run-sha256sum.sh +++ b/scripts/run-sha256sum.sh @@ -1,15 +1,38 @@ #!/bin/bash +# Check if 'sha256sum' command is available on the system if ! command -v sha256sum &> /dev/null then - printf "sha256sum could not be found" - exit + # If 'sha256sum' is not found, print an error message + printf "sha256sum could not be found\n" + # Exit the script with a non-zero status to indicate failure + exit 1 fi +# Assign the first command-line argument to the variable SHA_DIR SHA_DIR=$1 +# Ensure that SHA_DIR is provided and is a directory +if [ -z "$SHA_DIR" ]; then + printf "Usage: $0 \n" + exit 1 +elif [ ! -d "$SHA_DIR" ]; then + printf "Error: $SHA_DIR is not a directory or does not exist.\n" + exit 1 +fi + +# Use 'find' to locate all files within SHA_DIR +# For each found file, execute 'sha256sum' to calculate its SHA256 checksum +# Append all checksums to 'checksum.list' +find "$SHA_DIR" -type f -exec sha256sum "{}" + > checksum.list + +# Print a header message indicating that checksums have been calculated +printf "Checksum of all files in %s:\n" "$SHA_DIR" + +# Calculate the SHA256 checksum of the entire 'checksum.list' file +# Extract only the checksum value using 'awk' (ignoring the filename) +# Print the aggregated checksum with indentation for readability +printf "\t%s\n" "$(sha256sum checksum.list | awk '{print $1}')" -find $SHA_DIR -type f -exec sha256sum "{}" + > checksum.list -printf "Checksum of all files in $SHA_DIR:\n" -printf "\t%s\n" $(sha256sum checksum.list | awk '{print $1}') -printf "Please view checksum.list for individual files\n" +# Inform the user that individual file checksums are available in 'checksum.list' +printf "Please view checksum.list for individual file checksums.\n" From 8c9e7dc71e70200285d013af702c35e6be2bac90 Mon Sep 17 00:00:00 2001 From: alexander-sei Date: Mon, 4 Nov 2024 02:45:05 +0100 Subject: [PATCH 5/5] Update snapshot and statesync scripts --- scripts/run_snapshot.sh | 76 ++++++++++++++++++++++++++++++++++------- scripts/state_sync.sh | 64 +++++++++++++++++----------------- 2 files changed, 97 insertions(+), 43 deletions(-) diff --git a/scripts/run_snapshot.sh b/scripts/run_snapshot.sh index 2462cc151e..69bc4754f0 100644 --- a/scripts/run_snapshot.sh +++ b/scripts/run_snapshot.sh @@ -1,28 +1,80 @@ #!/bin/bash +# Check if the correct number of arguments is provided +if [ "$#" -ne 3 ]; then + echo "Usage: $0 INITIAL_HALT_HEIGHT SNAPSHOT_INTERVAL CHAIN_ID" + exit 1 +fi + INITIAL_HALT_HEIGHT=$1 SNAPSHOT_INTERVAL=$2 CHAIN_ID=$3 -systemctl stop seid +# Define variables for paths based on the home directory +SEI_DIR="$HOME/.sei" +CONFIG_FILE="$SEI_DIR/config/app.toml" +SNAPSHOT_DIR="$HOME/snapshots" +SEID_BIN="$HOME/go/bin/seid" + +# Ensure the seid binary exists +if [ ! -x "$SEID_BIN" ]; then + echo "Error: seid binary not found at $SEID_BIN" + exit 1 +fi + +# Stop the seid service if it's managed by systemd +if systemctl is-active --quiet seid; then + systemctl stop seid + echo "Stopped seid service." +else + echo "seid service is not running." +fi -sed -i -e 's/pruning = .*/pruning = "custom"/' /root/.sei/config/app.toml -sed -i -e 's/pruning-keep-recent = .*/pruning-keep-recent = "1"/' /root/.sei/config/app.toml -sed -i -e 's/pruning-keep-every = .*/pruning-keep-every = "0"/' /root/.sei/config/app.toml -sed -i -e 's/pruning-interval = .*/pruning-interval = "1"/' /root/.sei/config/app.toml +# Update pruning settings in the configuration file +if [ -f "$CONFIG_FILE" ]; then + sed -i -e 's/pruning = .*/pruning = "custom"/' "$CONFIG_FILE" + sed -i -e 's/pruning-keep-recent = .*/pruning-keep-recent = "1"/' "$CONFIG_FILE" + sed -i -e 's/pruning-keep-every = .*/pruning-keep-every = "0"/' "$CONFIG_FILE" + sed -i -e 's/pruning-interval = .*/pruning-interval = "1"/' "$CONFIG_FILE" + echo "Updated pruning settings in $CONFIG_FILE." +else + echo "Error: Configuration file $CONFIG_FILE not found." + exit 1 +fi -mkdir -p /root/snapshots +# Create the snapshots directory if it doesn't exist +mkdir -p "$SNAPSHOT_DIR" +echo "Ensured snapshot directory exists at $SNAPSHOT_DIR." +# Initialize halt height HALT_HEIGHT=$INITIAL_HALT_HEIGHT + +# Start the snapshot loop while true do - sed -i -e 's/halt-height = .*/halt-height = '$HALT_HEIGHT'/' /root/.sei/config/app.toml - /root/go/bin/seid start --trace --chain-id $CHAIN_ID + # Update the halt height in the configuration file + sed -i -e "s/halt-height = .*/halt-height = $HALT_HEIGHT/" "$CONFIG_FILE" + echo "Set halt-height to $HALT_HEIGHT in $CONFIG_FILE." + + # Start the seid node with tracing + echo "Starting seid node with chain ID $CHAIN_ID and halt height $HALT_HEIGHT." + "$SEID_BIN" start --trace --chain-id "$CHAIN_ID" & + SEID_PID=$! + + # Wait for the node to initialize (you might need to adjust the sleep duration) + sleep 10 + + # Take a snapshot at the current halt height start_time=$(date +%s) - /root/go/bin/seid tendermint snapshot $HALT_HEIGHT + "$SEID_BIN" tendermint snapshot "$HALT_HEIGHT" end_time=$(date +%s) elapsed=$(( end_time - start_time )) - echo "Backed up snapshot for height "$HALT_HEIGHT" which took "$elapsed" seconds" - HALT_HEIGHT=$(expr $HALT_HEIGHT + $SNAPSHOT_INTERVAL) - cd $HOME + echo "Backed up snapshot for height $HALT_HEIGHT which took $elapsed seconds." + + # Increment the halt height for the next snapshot + HALT_HEIGHT=$(( HALT_HEIGHT + SNAPSHOT_INTERVAL )) + echo "Next halt height set to $HALT_HEIGHT." + + # Navigate back to the home directory + cd "$HOME" done diff --git a/scripts/state_sync.sh b/scripts/state_sync.sh index 933af0bfda..5639f3bb7b 100755 --- a/scripts/state_sync.sh +++ b/scripts/state_sync.sh @@ -1,53 +1,55 @@ #!/bin/bash -echo -n Chain ID: -read CHAIN_ID -echo -echo -n Your Key Name: -read KEY -echo -echo -n Your Key Password: -read PASSWORD -echo -echo -n Moniker: -read MONIKER -echo -echo -n "Seid version commit (e.g. 5f3f795fc612c796a83726a0bbb46658586ca8fe):" -read REQUIRED_COMMIT -echo + +# Prompt for the State Sync RPC Endpoint and store it in STATE_SYNC_RPC echo -n State Sync RPC Endpoint: read STATE_SYNC_RPC echo + +# Prompt for the State Sync Peer and store it in STATE_SYNC_PEER echo -n State Sync Peer: read STATE_SYNC_PEER echo -COMMIT=$(seid version --long | grep commit) -COMMITPARTS=($COMMIT) -if [ ${COMMITPARTS[1]} != $REQUIRED_COMMIT ] -then - echo "incorrect seid version" - exit 1 -fi -mkdir $HOME/key_backup -printf ""$PASSWORD"\n"$PASSWORD"\n"$PASSWORD"\n" | seid keys export $KEY > $HOME/key_backup/key +# Create a backup directory for keys +mkdir -p $HOME/key_backup + +# Backup the validator key and state files cp $HOME/.sei/config/priv_validator_key.json $HOME/key_backup cp $HOME/.sei/data/priv_validator_state.json $HOME/key_backup -mkdir $HOME/.sei_backup + +# Create a backup directory for the entire .sei configuration +mkdir -p $HOME/.sei_backup + +# Move existing config, data, and wasm directories to the backup directory mv $HOME/.sei/config $HOME/.sei_backup mv $HOME/.sei/data $HOME/.sei_backup mv $HOME/.sei/wasm $HOME/.sei_backup + +# Remove the data and wasm folder cd $HOME/.sei && ls | grep -xv "cosmovisor" | xargs rm -rf -seid tendermint unsafe-reset-all -seid init --chain-id $CHAIN_ID $MONIKER -printf ""$PASSWORD"\n"$PASSWORD"\n"$PASSWORD"\n" | seid keys import $KEY $HOME/key_backup/key + +# Restore the validator key and state files from the backup +mkdir -p $HOME/.sei/config +mkdir -p $HOME/.sei/data cp $HOME/key_backup/priv_validator_key.json $HOME/.sei/config/ cp $HOME/key_backup/priv_validator_state.json $HOME/.sei/data/ -LATEST_HEIGHT=$(curl -s $STATE_SYNC_RPC/block | jq -r .result.block.header.height); \ -BLOCK_HEIGHT=$((LATEST_HEIGHT - 1000)); \ + +# Set up /tmp as a 12G RAM disk to allow for more than 400 state sync chunks +sudo umount -l /tmp && sudo mount -t tmpfs -o size=12G,mode=1777 overflow /tmp + +# Fetch the latest block height from the State Sync RPC endpoint +LATEST_HEIGHT=$(curl -s $STATE_SYNC_RPC/block | jq -r .result.block.header.height) +# Calculate the trust height (rounded down to the nearest 100,000) +BLOCK_HEIGHT=$(( (LATEST_HEIGHT / 100000) * 100000 )) +# Fetch the block hash at the trust height TRUST_HASH=$(curl -s "$STATE_SYNC_RPC/block?height=$BLOCK_HEIGHT" | jq -r .result.block_id.hash) + +# Update the config.toml file to enable state sync with the appropriate settings sed -i.bak -E "s|^(enable[[:space:]]+=[[:space:]]+).*$|\1true| ; \ s|^(rpc_servers[[:space:]]+=[[:space:]]+).*$|\1\"$STATE_SYNC_RPC,$STATE_SYNC_RPC\"| ; \ s|^(trust_height[[:space:]]+=[[:space:]]+).*$|\1$BLOCK_HEIGHT| ; \ s|^(trust_hash[[:space:]]+=[[:space:]]+).*$|\1\"$TRUST_HASH\"|" $HOME/.sei/config/config.toml + +# Set the persistent peers in the config.toml file to the specified State Sync Peer sed -i.bak -e "s|^persistent_peers *=.*|persistent_peers = \"$STATE_SYNC_PEER\"|" \ - $HOME/.sei/config/config.toml + $HOME/.sei/config/config.toml \ No newline at end of file