# State Sync Full Node

# Sync and Run a Full Bitmail Node using State Sync from a shell script

-- The shell script below will

  • Install All Dependancies
  • Install golang (this is only for a Linux AMD system)
  • Install Ingite
  • Clone the Bitmail Repo
  • Build the Binary
  • Initilize a Node
  • Set all nessary config.toml and app.toml variables
  • It also automatically querry's the blockchain to obtain the Trust Height and Trust Hash for latest state sync files
  • You can alter your Yournode name

# Instrucitons

Create a file called bootstrap.sh

nano bootstrap.sh

(optional) Make a working directory for this or run in your home folder or current working directory

mkdir bitmail-test-node
cd bitmail-test-node

Copy & paste the shell script below and save the file:

Turn it into an execitable:

chmod +x bootstrap.sh

Run the file

./bootstrap.sh
#!/usr/bin/env bash
# Bitmail Full Node Bootstrap + State Sync (sed-only; no tmp leftovers)
# - Probes RPCs, uses 2 if available, else duplicates the single working one
# - Rewrites [statesync] keys in-place with sed (enable=true, rpc_servers, trust_height/hash/period)
# - Sets API+Swagger, min gas price, seeds/peers, RPC exposure, timeout_commit

set -Eeuo pipefail

### ------- USER OPTIONS (override via env) -------
: "${YOURNODENAME:=MyBitmailNode}"
: "${CHAINID:=bitmailtestnet001}"
: "${DEFAULT_DENOM:=ubtml}"

# Candidate RPCs to probe (HTTP, must serve /status and /block)
RPC_CANDIDATES=(
  "http://172.104.47.54:26657"
  # add more if you have them
)

# P2P (IDs must match your network)
: "${SEEDS:=288d66e8c02539a430598ac5ffa01795584531e3@172.233.144.166:26656,51e019d3decdd7077a07b7110cad0ea5c49bdf3f@194.195.118.93:26656}"
: "${PERSISTENT_PEERS:=288d66e8c02539a430598ac5ffa01795584531e3@172.233.144.166:26656,51e019d3decdd7077a07b7110cad0ea5c49bdf3f@194.195.118.93:26656}"

# Node tuning
: "${MIN_GAS_PRICE:=0.0025ubtml}"
: "${TIMEOUT_COMMIT:=20s}"
: "${TRUST_PERIOD:=168h0m0s}"

### ------- helpers -------
log(){ printf "\033[1;36m[INFO]\033[0m %s\n" "$*"; }
warn(){ printf "\033[1;33m[WARN]\033[0m %s\n" "$*"; }
die(){ printf "\033[1;31m[ERR]\033[0m %s\n" "$*" >&2; exit 1; }
need(){ command -v "$1" >/dev/null 2>&1 || die "Missing dependency: $1"; }

### ------- deps -------
sudo true >/dev/null 2>&1 || die "Need sudo privileges"
for b in curl jq git sed awk tar; do need "$b"; done

if ! command -v go >/dev/null 2>&1; then
  log "Installing Go 1.23.1…"
  cd /tmp
  curl -fsSLO https://go.dev/dl/go1.23.1.linux-amd64.tar.gz
  sudo rm -rf /usr/local/go
  sudo tar -C /usr/local -xzf go1.23.1.linux-amd64.tar.gz
  {
    echo 'export GOROOT=/usr/local/go'
    echo 'export GOPATH=$HOME/go'
    echo 'export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin'
  } | tee -a "$HOME/.bashrc" >/dev/null
  export GOROOT=/usr/local/go
  export GOPATH=$HOME/go
  export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
fi

if ! command -v ignite >/dev/null 2>&1; then
  log "Installing Ignite CLI v0.27.1…"
  curl -s https://get.ignite.com/cli@v0.27.1 | bash
  sudo mv ignite /usr/local/bin
fi

### ------- get/build bitmaild -------
if [ ! -d "$HOME/bitmail" ]; then
  log "Cloning Bitmail repo…"
  git clone https://github.com/Cosmos-Guru/bitmail.git "$HOME/bitmail"
fi
cd "$HOME/bitmail"

log "Building bitmaild…"
if command -v ignite >/dev/null 2>&1; then
  ignite chain build
elif [ -f Makefile ]; then
  make install
else
  go build -o "$HOME/go/bin/bitmaild" ./cmd/bitmaild
fi
need bitmaild

### ------- init & paths -------
log "Initializing node…"
bitmaild init "$YOURNODENAME" --default-denom "$DEFAULT_DENOM" --chain-id "$CHAINID"

APP="$HOME/.bitmail/config/app.toml"
CFG="$HOME/.bitmail/config/config.toml"

### ------- choose RPCs -------
log "Probing RPC candidates…"
good=()
for u in "${RPC_CANDIDATES[@]}"; do
  base="${u%/}"
  if out=$(curl -s --max-time 3 "$base/status") && id=$(jq -r '.result.node_info.id // empty' <<<"$out"); then
    [ -n "$id" ] && { log "OK $base (id=$id)"; good+=("$base"); }
  fi
done

if [ "${#good[@]}" -eq 0 ]; then
  die "No working RPCs reachable from RPC_CANDIDATES."
elif [ "${#good[@]}" -eq 1 ]; then
  warn "Only one RPC reachable; duplicating it to satisfy light client."
  RPC1="${good[0]}"; RPC2="${good[0]}"
else
  RPC1="${good[0]}"; RPC2="${good[1]}"
fi
RPCS="${RPC1},${RPC2}"
log "Using rpc_servers = \"$RPCS\""

### ------- genesis -------
log "Fetching genesis from $RPC1 …"
mkdir -p "$HOME/.bitmail/config"
curl -s "${RPC1%/}/genesis" | jq -r '.result.genesis' > "$HOME/.bitmail/config/genesis.json" || die "Failed to write genesis.json"

### ------- app.toml -------
log "Enabling API+Swagger and setting min gas price…"
sed -i -E '/^\[api\]/,/^\[/{s/^(enable\s*=\s*).*/\1true/; s/^(swagger\s*=\s*).*/\1true/}' "$APP"
sed -i -E "s#^(minimum-gas-prices\s*=\s*).*\$#\1\"$MIN_GAS_PRICE\"#" "$APP"

### ------- config.toml: P2P & RPC exposure -------
log "Setting seeds/persistent_peers/RPC exposure/timeout_commit…"
sed -i -E "s#^(seeds\s*=\s*).*\$#\1\"$SEEDS\"#" "$CFG"
sed -i -E "s#^(persistent_peers\s*=\s*).*\$#\1\"$PERSISTENT_PEERS\"#" "$CFG"
sed -i -E 's#^laddr = "tcp://127\.0\.0\.1:26657"#laddr = "tcp://0.0.0.0:26657"#' "$CFG"
sed -i -E "s#^(timeout_commit\s*=\s*).*\$#\1\"$TIMEOUT_COMMIT\"#" "$CFG"

### ------- statesync: compute trust params -------
log "Computing trust height/hash from $RPC1 …"
LATEST=$(curl -s "${RPC1%/}/status" | jq -r '.result.sync_info.latest_block_height // 0')
[ "$LATEST" -gt 0 ] || die "latest_block_height not found at $RPC1"
TRUST_HEIGHT=$(( LATEST/1000*1000 ))
[ "$TRUST_HEIGHT" -gt 0 ] || TRUST_HEIGHT="$LATEST"
TRUST_HASH=$(curl -s "${RPC1%/}/block?height=${TRUST_HEIGHT}" | jq -r '.result.block_id.hash // empty')
[ -n "$TRUST_HASH" ] || die "trust_hash not found at height $TRUST_HEIGHT from $RPC1"

### ------- statesync: write keys IN-PLACE with sed -------
log "Writing [statesync] keys in config.toml …"
# If [statesync] exists, update keys inside that section.
if grep -q '^\[statesync\]' "$CFG"; then
  sed -i -E "/^\[statesync\]/,/^\[/{ \
    s/^(enable\s*=\s*).*/\1true/; \
    s#^(rpc_servers\s*=\s*).*\$#\1\"$RPCS\"#; \
    s#^(trust_height\s*=\s*).*\$#\1$TRUST_HEIGHT#; \
    s#^(trust_hash\s*=\s*).*\$#\1\"$TRUST_HASH\"#; \
    s#^(trust_period\s*=\s*).*\$#\1\"$TRUST_PERIOD\"#; \
  }" "$CFG"
else
  # Append a canonical statesync block if missing entirely
  cat >> "$CFG" <<EOF

[statesync]
enable = true
rpc_servers = "$RPCS"
trust_height = $TRUST_HEIGHT
trust_hash = "$TRUST_HASH"
trust_period = "$TRUST_PERIOD"
EOF
fi

### ------- summary -------
log "Summary:"
echo "  Moniker           : $YOURNODENAME"
echo "  Chain ID          : $CHAINID"
echo "  RPC servers       : $RPCS"
echo "  Trust height/hash : $TRUST_HEIGHT / $TRUST_HASH"
echo "  Seeds             : $SEEDS"
echo "  Persistent peers  : $PERSISTENT_PEERS"

### ------- start -------
log "Starting bitmaild…"
exec bitmaild start