#
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