# 0G Storage Node

## Resources

| Website | <https://0g.ai/>                                      |
| ------- | ----------------------------------------------------- |
| Github  | <https://github.com/0glabs>                           |
| x.com   | [https://x.com/0G\_labs](https://twitter.com/0G_labs) |
| Discord | <https://discord.com/invite/0glabs>                   |
| Docs    | <https://docs.0g.ai/0g-doc>                           |

## Prerequisite

0G Storage and DA services interact with on-chain contracts for blob root confirmation and PoRA mining.

This step is performed after your [validator](https://app.gitbook.com/o/CCRLLakO01pbPnsbSqvj/s/socsWgfdMBUSXoC8Z3Gv/~/changes/35/testnets/0g-zero-gravity/0g-zero-gravity-validator-node) has been installed and created.

For official deployed contract addresses, visit [this page](https://docs.0g.ai/0g-doc/docs/contract-addresses)

## Hardware requirements

<table data-view="cards"><thead><tr><th>CPU</th><th>RAM</th><th>Storage</th><th>Network</th><th>OS</th></tr></thead><tbody><tr><td>4 cores</td><td>16 GB</td><td>1 TB NVME</td><td>500 MBps</td><td>Linux (Ubuntu 20.04 x64)</td></tr></tbody></table>

## Installation 💾

Install dependencies

```bash
sudo apt update && sudo apt upgrade -y
sudo apt install curl git wget htop tmux build-essential jq make lz4 gcc unzip -y
```

Install Rust

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env

cargo --version
rustc --version
```

Install GO 1.22.2

```bash
sudo rm -rf /usr/local/go && \
curl -L https://go.dev/dl/go1.22.2.linux-amd64.tar.gz | sudo tar -xzf - -C /usr/local && \
echo 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' >> $HOME/.bash_profile && \
source .bash_profile && \
go version
```

Build binary from source

```bash
git clone -b v1.0.0 https://github.com/0glabs/0g-storage-node.git

cd $HOME/0g-storage-node
git stash
git fetch --all --tags
git checkout 347cd3e
git submodule update --init
cargo build --release

cp $HOME/0g-storage-node/run/config-testnet-turbo.toml $HOME/0g-storage-node/run/config.toml
```

check zgs version

```bash
$HOME/0g-storage-node/target/release/zgs_node --version
```

Set vars. you found more from official docs

```bash
export ZGS_LOG_DIR="$HOME/0g-storage-node/run/log"
export ZGS_LOG_CONFIG_FILE="$HOME/0g-storage-node/run/log_config"
export LOG_CONTRACT_ADDRESS="0xbD75117F80b4E22698D0Cd7612d92BDb8eaff628"
export MINE_CONTRACT="0x3A0d1d67497Ad770d6f72e7f4B8F0BAbaa2A649C"
export REWARD_CONTRACT="0xd3D4D91125D76112AE256327410Dd0414Ee08Cb4"
export ZGS_LOG_SYNC_BLOCK=326165
```

Set Ethereum private key. Your private key (64 chars, no '0x' prefix, include leading zeros): Your private key (without the `0x` prefix) if you want to participate in PoRA mining and earn rewards.

&#x20;After entering the next command, a field will appear in which you should enter the key you received in the previous step. Note that the text you enter will not be displayed.

```bash
read -sp "Enter your extracted private key: " PRIVATE_KEY && echo
```

Set the miner\_key in the config.toml file

```bash
sed -i 's|^miner_key = ""|miner_key = "'"$PRIVATE_KEY"'"|' $HOME/0g-storage-node/run/config.toml
```

Set var the Storage Node IP address

```bash
ZGS_IP=$(wget -qO- eth0.me)
```

Edit the storage node config

```bash
sed -i '
s|# network_dir = "network"|network_dir = "network"|g
s|# network_enr_tcp_port = 1234|network_enr_tcp_port = 1234|g
s|# network_enr_udp_port = 1234|network_enr_udp_port = 1234|g
s|# network_libp2p_port = 1234|network_libp2p_port = 1234|g
s|# network_discovery_port = 1234|network_discovery_port = 1234|g
s|# rpc_enabled = true|rpc_enabled = true|g
s|# db_dir = "db"|db_dir = "db"|g
s|# log_config_file = "log_config"|log_config_file = "log_config"|g
s|# log_directory = "log"|log_directory = "log"|g
s|# network_enr_address = ""|network_enr_address = "'"$ZGS_IP"'"|g
' $HOME/0g-storage-node/run/config.toml
```

```bash
sed -i '
s|^log_sync_start_block_number = .*|log_sync_start_block_number = '"$ZGS_LOG_SYNC_BLOCK"'|g
s|^log_config_file = .*|log_config_file = "'"$ZGS_LOG_CONFIG_FILE"'"|g
s|^log_directory = .*|log_directory = "'"$ZGS_LOG_DIR"'"|g
s|^mine_contract_address = .*|mine_contract_address = "'"$MINE_CONTRACT"'"|g
s|^log_contract_address = .*|log_contract_address = "'"$LOG_CONTRACT_ADDRESS"'"|g
s|^reward_contract_address = .*|reward_contract_address = "'"$REWARD_CONTRACT"'"|g
' $HOME/0g-storage-node/run/config.toml
```

Update boot nodes addresses

```bash
sed -i 's|^network_boot_nodes = .*|network_boot_nodes = ["/ip4/47.251.117.133/udp/1234/p2p/16Uiu2HAmTVDGNhkHD98zDnJxQWu3i1FL1aFYeh9wiQTNu4pDCgps","/ip4/47.76.61.226/udp/1234/p2p/16Uiu2HAm2k6ua2mGgvZ8rTMV8GhpW71aVzkQWy7D37TTDuLCpgmX","/ip4/47.251.79.83/udp/1234/p2p/16Uiu2HAkvJYQABP1MdvfWfUZUzGLx1sBSDZ2AT92EFKcMCCPVawV","/ip4/47.238.87.44/udp/1234/p2p/16Uiu2HAmFGsLoajQdEds6tJqsLX7Dg8bYd2HWR4SbpJUut4QXqCj","/ip4/47.251.78.104/udp/1234/p2p/16Uiu2HAmSe9UWdHrqkn2mKh99b9DwYZZcea6krfidtU3e5tiHiwN","/ip4/47.76.30.235/udp/1234/p2p/16Uiu2HAm5tCqwGtXJemZqBhJ9JoQxdDgkWYavfCziaqaAYkGDSfU"]|g' ~/0g-storage-node/run/config.toml
```

Set `blockchain_rpc_endpoint` from your validator's (json-rpc endpoint). To connect your storage node to the validator.

{% hint style="info" %}
You can use the json-rpc of your validator (which you can see in the $HOME/.0gchain/config/app.toml file) or use any available from the community.<br>

You should also have the indexer enabled in the validator config:\
sed -i -e "s/^indexer \*=.\*/indexer = \\"kv"/" $HOME/.0gchain/config/config.toml
{% endhint %}

Official 0g rpc endpoint:

```bash
BLOCKCHAIN_RPC_ENDPOINT="https://evmrpc-testnet.0g.ai"
sed -i 's|^blockchain_rpc_endpoint = ".*"|blockchain_rpc_endpoint = "'"$BLOCKCHAIN_RPC_ENDPOINT"'"|' $HOME/0g-storage-node/run/config.toml
echo "export BLOCKCHAIN_RPC_ENDPOINT=\"$BLOCKCHAIN_RPC_ENDPOINT\"" >> ~/.bash_profile
```

Create a service file

```bash
sudo tee /etc/systemd/system/zgs.service > /dev/null <<EOF
[Unit]
Description=ZGS Node
After=network.target

[Service]
User=$USER
WorkingDirectory=$HOME/0g-storage-node/run
ExecStart=$HOME/0g-storage-node/target/release/zgs_node --config $HOME/0g-storage-node/run/config.toml
Restart=on-failure
RestartSec=10
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF
```

Start the node

```bash
sudo systemctl daemon-reload && sudo systemctl enable zgs && sudo systemctl restart zgs
```

## Useful commands ⚙️

Stop the storage node

```bash
sudo systemctl stop zgs
```

Check list of logs

```bash
ls ~/0g-storage-node/run/log/
```

Check logs on a specific date. For example:

```bash
tail -f ~/0g-storage-node/run/log/zgs.log.2024-06-04
```

Check the latest logs file

```bash
tail -f ~/0g-storage-node/run/log/zgs.log.$(TZ=UTC date +%Y-%m-%d)
```

Check sync status

```bash
while true; do 
    response=$(curl -s -X POST http://localhost:5678 -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"zgs_getStatus","params":[],"id":1}')
    logSyncHeight=$(echo $response | jq '.result.logSyncHeight')
    connectedPeers=$(echo $response | jq '.result.connectedPeers')
    echo -e "logSyncHeight: \033[32m$logSyncHeight\033[0m, connectedPeers: \033[34m$connectedPeers\033[0m"
    sleep 5; 
done
```

Check version

```bash
cd $HOME/0g-storage-node && git log --decorate=short --oneline | grep "tag: v" | head -n 1 && git log -1 --pretty=oneline
```

## Delete node 🗑️

```bash
sudo systemctl stop zgs && sudo systemctl disable zgs
sudo rm -rf /etc/systemd/system/zgs.service
sudo rm $(which zgs)
sudo rm -rf $HOME/0g-storage-node
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://cryptomolot.gitbook.io/cryptomolot-docs/testnets/0g-zero-gravity/0g-storage-node.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
