カルダノステークプール構築手順

このマニュアルでは、1つのブロックプロデューサーノードと1つのリレーノードで構成し、ソースコードからカルダノステークプールをセットアップする手順となっております。

🎉 ∞ お知らせ

このマニュアルは、X Stake PoolオペレータのBTBFCoinCashewより許可を得て、日本語翻訳しております。

このマニュアルは、カルダノノードv1.25.1に対応しています。(CLIコマンド修正済み) ドキュメント更新情報はこちら 最終更新日:2021年2月21日の時点guide version 3.2.1

🏁 0. 前提条件

🧙♂ ステークプールオペレータの必須スキル

カルダノステークプールを運営するには、以下のスキルを必要とします。

  • カルダノノードを継続的にセットアップ、実行、維持する運用スキル

  • ノードを24時間年中無休で維持するというコミット

  • システム運用スキル

  • サーバ管理スキル (運用および保守).

  • 開発と運用経験 (DevOps)

  • サーバ強化とセキュリティに関する知識

  • カルダノ財団公式ステークプールセットアップコース受講

🛑 このマニュアルを進めるには、上記のスキル要件を必要とします 🚧

🎗 ステークプールハードウェア要件(最小構成)

  • 2つのサーバー: ブロックプロデューサーノード用1台、 リレーノード用1台

  • エアギャップオフラインマシン1台 (コールド環境)

  • オペレーティング・システム: 64-bit Linux (Ubuntu 20.04 LTS)

  • プロセッサー: 1.6GHz以上(ステークプールまたはリレーの場合は2Ghz以上)の2つ以上のコアを備えたIntelまたはAMD x86プロセッサー

  • メモリー: 4GB RAM(リレーまたはステークプールでは8GB)

  • ストレージ: 24GB SSD

  • インターネット: 10 Mbps以上のブロードバンド回線.

  • データプラン: 1時間あたり1GBの帯域. 1ヶ月あたり720GB.

  • 電力: 安定供給された電力

  • ADA残高: 505 ADA以上

🏋♂ ステークプールハードウェア要件(推奨構成)

  • 3つのサーバー: ブロックプロデューサーノード用1台、 リレーノード用2台

  • エアギャップオフラインマシン1台 (コールド環境)

  • オペレーティング・システム: 64-bit Linux (i.e. Ubuntu 20.04 LTS)

  • プロセッサー: 4 core以上の CPU

  • メモリー: 8GB+ RAM

  • ストレージ: 256GB+ SSD

  • インターネット: 100 Mbps以上のブロードバンド回線

  • データプラン: 無制限

  • 電力: 無停電電源装置(UPS)による電源管理

  • ADA残高: ステークプールに対する保証金をご自身で定める分

🔓 ステークプールの推奨セキュリティ設定

ステークプールのサーバを強化するには、以下の内容を実施して下さい。

🛠 Ubuntuセットアップガイド

絶賛翻訳中

🧱 ノードを再構築したい場合

もしノードインストールを初めからやり直したい場合は項目18.2で、リセットの方法を確認して下さい。

🧱 試しにノードを起動してみたい方へ

Linuxサーバのコマンドや、ノード起動などお試しテストでやってみたい方は、項目の1,2,3,4, 5をやってみましょう! この項目はブロックチェーンには直接的に影響がないので、たとえ間違ったコマンドを送信してもネットワークには問題ございません。

🏭 1. CabalとGHCをインストールします

ターミナルを起動し、以下のコマンドを入力しましょう!

まずはじめに、パッケージを更新しUbuntuを最新の状態に保ちます。

sudo apt-get update -y
sudo apt-get upgrade -y
sudo apt-get install git jq bc automake tmux rsync htop curl build-essential pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev libsystemd-dev zlib1g-dev make g++ wget libncursesw5 libtool autoconf -y

次に、Libsodiumをインストールします。

mkdir $HOME/git
cd $HOME/git
git clone https://github.com/input-output-hk/libsodium
cd libsodium
git checkout 66f017f1
./autogen.sh
./configure
make
sudo make install

Cabalをインストールします。

cd
wget https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz
tar -xf cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz
rm cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz cabal.sig
mkdir -p $HOME/.local/bin
mv cabal $HOME/.local/bin/

GHCをインストールします。

wget https://downloads.haskell.org/ghc/8.10.2/ghc-8.10.2-x86_64-deb9-linux.tar.xz
tar -xf ghc-8.10.2-x86_64-deb9-linux.tar.xz
rm ghc-8.10.2-x86_64-deb9-linux.tar.xz
cd ghc-8.10.2
./configure
sudo make install

環境変数を設定しパスを通します。 ノードの場所は $NODE_HOME に設定されます。 最新のノード構成ファイルは$NODE_CONFIG$NODE_BUILD_NUMによって取得されます。

echo PATH="$HOME/.local/bin:$PATH" >> $HOME/.bashrc
echo export LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH" >> $HOME/.bashrc
echo export NODE_HOME=$HOME/cardano-my-node >> $HOME/.bashrc
echo export NODE_CONFIG=mainnet>> $HOME/.bashrc
echo export NODE_BUILD_NUM=$(curl https://hydra.iohk.io/job/Cardano/iohk-nix/cardano-deployment/latest-finished/download/1/index.html | grep -e "build" | sed 's/.*build\/\([0-9]*\)\/download.*/\1/g') >> $HOME/.bashrc
source $HOME/.bashrc

Cabalを更新し、正しいバージョンが正常にインストールされていることを確認して下さい。

cabal update
cabal -V
ghc -V

Cabalのライブラリーバージョンは「3.2.0.0」で GHCのバージョンは「8.10.2」であることを確認してください。

🏗 2. ソースコードからノードを構築する

Gitからソースコードをダウンロードし、最新のタグに切り替えます。

cd $HOME/git
git clone https://github.com/input-output-hk/cardano-node.git
cd cardano-node
git fetch --all --recurse-submodules --tags
git checkout tags/1.25.1

Cabalのビルドオプションを構成します。

cabal configure -O0 -w ghc-8.10.2

Cabal構成、プロジェクト設定を更新し、ビルドフォルダーをリセットします。

echo -e "package cardano-crypto-praos\n flags: -external-libsodium-vrf" > cabal.project.local
sed -i $HOME/.cabal/config -e "s/overwrite-policy:/overwrite-policy: always/g"
rm -rf $HOME/git/cardano-node/dist-newstyle/build/x86_64-linux/ghc-8.10.2

カルダノノードをビルドします。

cabal build cardano-cli cardano-node

サーバスペックによって、ビルド完了までに数分から数時間かかる場合があります。

cardano-cliファイルと cardano-nodeファイルをbinディレクトリにコピーします。

sudo cp $(find $HOME/git/cardano-node/dist-newstyle/build -type f -name "cardano-cli") /usr/local/bin/cardano-cli
sudo cp $(find $HOME/git/cardano-node/dist-newstyle/build -type f -name "cardano-node") /usr/local/bin/cardano-node

cardano-clicardano-nodeのバージョンが上記で指定したGitタグバージョンであることを確認してください。

cardano-node version
cardano-cli version

📐 3. ノードを構成する

ノード構成に必要な config.json、genesis.json、及び topology.json ファイルを取得します。

mkdir $NODE_HOME
cd $NODE_HOME
wget -N https://hydra.iohk.io/build/${NODE_BUILD_NUM}/download/1/${NODE_CONFIG}-byron-genesis.json
wget -N https://hydra.iohk.io/build/${NODE_BUILD_NUM}/download/1/${NODE_CONFIG}-topology.json
wget -N https://hydra.iohk.io/build/${NODE_BUILD_NUM}/download/1/${NODE_CONFIG}-shelley-genesis.json
wget -N https://hydra.iohk.io/build/${NODE_BUILD_NUM}/download/1/${NODE_CONFIG}-config.json

以下のコードを実行し config.jsonファイルを更新します。

  • TraceBlockFetchDecisionsを「true」に変更します。

sed -i ${NODE_CONFIG}-config.json \
-e "s/TraceBlockFetchDecisions\": false/TraceBlockFetchDecisions\": true/g"

環境変数を追加し、.bashrcファイルを更新します。

echo export CARDANO_NODE_SOCKET_PATH="$NODE_HOME/db/socket" >> $HOME/.bashrc
source $HOME/.bashrc

🤖 4. ノード起動スクリプトを作成する。

起動スクリプトには、ディレクトリ、ポート番号、DBパス、構成ファイルパス、トポロジーファイルパスなど、カルダノノードを実行するために必要な変数が含まれています。

全行をコピーしコマンドラインに送信します。

リレーノード1
ブロックプロデューサーノード
リレーノード1
cat > $NODE_HOME/startRelayNode1.sh << EOF
#!/bin/bash
DIRECTORY=\$NODE_HOME
PORT=6000
HOSTADDR=0.0.0.0
TOPOLOGY=\${DIRECTORY}/${NODE_CONFIG}-topology.json
DB_PATH=\${DIRECTORY}/db
SOCKET_PATH=\${DIRECTORY}/db/socket
CONFIG=\${DIRECTORY}/${NODE_CONFIG}-config.json
cardano-node run --topology \${TOPOLOGY} --database-path \${DB_PATH} --socket-path \${SOCKET_PATH} --host-addr \${HOSTADDR} --port \${PORT} --config \${CONFIG}
EOF
ブロックプロデューサーノード
cat > $NODE_HOME/startBlockProducingNode.sh << EOF
#!/bin/bash
DIRECTORY=\$NODE_HOME
PORT=6000
HOSTADDR=0.0.0.0
TOPOLOGY=\${DIRECTORY}/${NODE_CONFIG}-topology.json
DB_PATH=\${DIRECTORY}/db
SOCKET_PATH=\${DIRECTORY}/db/socket
CONFIG=\${DIRECTORY}/${NODE_CONFIG}-config.json
cardano-node run --topology \${TOPOLOGY} --database-path \${DB_PATH} --socket-path \${SOCKET_PATH} --host-addr \${HOSTADDR} --port \${PORT} --config \${CONFIG}
EOF

✅ 5. ノードを起動します。

起動スクリプトに実行権限を付与し、ブロックチェーンの同期を開始します。

リレーノードから実施します。

リレーノード
ブロックプロデューサーノード
リレーノード
cd $NODE_HOME
chmod +x startRelayNode1.sh
./startRelayNode1.sh
ブロックプロデューサーノード
cd $NODE_HOME
chmod +x startBlockProducingNode.sh
./startBlockProducingNode.sh

slot番号などが表示され、勢いよくログが流れていたら起動成功です ただ、このままでは画面を閉じるとノードが終了するので次の工程に移ってください。

🛑 ノードを停止するには「Ctrl」+「c」を押します。

ヒント: 複数のノードをセットアップする場合、同期が完了したDBディレクトリを他のサーバにコピーすることにより、同期時間を節約することができます。

一旦ノードを停止します。

Ctrl+C

🛠 5-1.自動起動とバックグラウンド起動を設定する(systemd+tmux)

先程のスクリプトだけでは、ターミナル画面を閉じるとノードが終了してしまうので、スクリプトをサービスとして登録し、自動起動設定と別セッションで起動するように設定しましょう

🍰 ステークプールにsystemdを使用するメリット

  1. メンテナンスや停電など、自動的にコンピュータが再起動したときステークプールを自動起動します。

  2. クラッシュしたステークプールプロセスを自動的に再起動します。

  3. ステークプールの稼働時間とパフォーマンスをレベルアップさせます。

🛠 セットアップ手順

始める前にステークプールが停止しているか確認してください。

killall -s 2 cardano-node

以下のコードを実行して、ユニットファイルを作成します。

リレーノード1
ブロックプロデューサーノード
リレーノード1
cat > $NODE_HOME/cardano-node.service << EOF
# The Cardano node service (part of systemd)
# file: /etc/systemd/system/cardano-node.service
[Unit]
Description = Cardano node service
Wants = network-online.target
After = network-online.target
[Service]
User = $(whoami)
Type = forking
WorkingDirectory= $NODE_HOME
ExecStart = /usr/bin/tmux new -d -s cnode
ExecStartPost = /usr/bin/tmux send-keys -t cnode $NODE_HOME/startRelayNode1.sh Enter
KillSignal=SIGINT
RestartKillSignal=SIGINT
TimeoutStopSec=2
LimitNOFILE=32768
Restart=always
RestartSec=5
[Install]
WantedBy = multi-user.target
EOF
ブロックプロデューサーノード
cat > $NODE_HOME/cardano-node.service << EOF
# The Cardano node service (part of systemd)
# file: /etc/systemd/system/cardano-node.service
[Unit]
Description = Cardano node service
Wants = network-online.target
After = network-online.target
[Service]
User = $(whoami)
Type = forking
WorkingDirectory= $NODE_HOME
ExecStart = /usr/bin/tmux new -d -s cnode
ExecStartPost = /usr/bin/tmux send-keys -t cnode $NODE_HOME/startBlockProducingNode.sh Enter
KillSignal=SIGINT
RestartKillSignal=SIGINT
TimeoutStopSec=2
LimitNOFILE=32768
Restart=always
RestartSec=5
[Install]
WantedBy = multi-user.target
EOF

/etc/systemd/systemにユニットファイルをコピーして、権限を付与します。

sudo cp $NODE_HOME/cardano-node.service /etc/systemd/system/cardano-node.service
sudo chmod 644 /etc/systemd/system/cardano-node.service

次のコマンドを実行して、OS起動時にサービスの自動起動を有効にします。

sudo systemctl daemon-reload
sudo systemctl enable cardano-node
sudo systemctl start cardano-node

5-2.gLiveView ノードステータスモニターをインストールしますに進んでください。

以下は、systemdを有効活用するためのコマンドです。

****⛓ システム起動後に、ログモニターを表示します

tmux a -t cnode

バックグラウンド起動中のセッション(別画面)を確認する

tmux ls

🚧 セッションをバックグラウンド実行に切り替え、コマンドラインを表示します。

press Ctrl + b を押した後、すぐに d (デタッチ)

✅ ノードが実行されているか確認します。

sudo systemctl is-active cardano-node

🔎 ノードのステータスを表示します。

sudo systemctl status cardano-node

🔄 ノードサービスを再起動します。

sudo systemctl reload-or-restart cardano-node

🛑 ノードサービスを停止します。

sudo systemctl stop cardano-node

🗄 ログのフィルタリング

journalctl --unit=cardano-node --since=yesterday
journalctl --unit=cardano-node --since=today
journalctl --unit=cardano-node --since='2020-07-29 00:00:00' --until='2020-07-29 12:00:00'

🛠 5-2.gLiveView ノードステータスモニターをインストールします

現在のcardano-nodeはログが流れる画面で、何が表示されているのかよくわかりません。 それを視覚的に確認できるツールがgLiveViewです。

gLiveViewは重要なノードステータス情報を表示し、systemdサービスとうまく連携します。1.23.0から正式にLiveViewが削除されgLiveViewは代替ツールとして利用できます。このツールを作成した Guild Operators の功績によるものです。

Guild LiveViewをインストールします。

mkdir $NODE_HOME/scripts
cd $NODE_HOME/scripts
sudo apt install bc tcptraceroute -y
curl -s -o gLiveView.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/gLiveView.sh
curl -s -o env https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/env
chmod 755 gLiveView.sh

env ファイルによってファイル構成を指定できます。 ノードのポート番号を6000以外に設定している場合は、envファイルを開いて修正してください。

sed -i env \
-e "s/\#CONFIG=\"\${CNODE_HOME}\/files\/config.json\"/CONFIG=\"\${NODE_HOME}\/mainnet-config.json\"/g" \
-e "s/\#SOCKET=\"\${CNODE_HOME}\/sockets\/node0.socket\"/SOCKET=\"\${NODE_HOME}\/db\/socket\"/g"

Guild Liveviewを起動します。

./gLiveView.sh

このツールを立ち上げてもノードは起動しません。ノードは別途起動しておく必要があります リレー/BPは自動判別されます。 リレーノードでは基本情報に加え、トポロジー接続状況を確認できます。 BPノードでは基本情報に加え、KES有効期限、ブロック生成状況を確認できます。

[p]リレーノード用リモートピア分析について ピアにpingを送信する際ICMPpingを使用します。リモートピアのファイアウォールがICMPトラフィックを受け付ける場合のみ機能します。

Guild Live View

詳しくは開発元のドキュメントを参照してください official Guild Live View docs.

この画面が表示され、ノードが同期したら準備完了です。

🔮 6. ブロックプロデューサーノードを構築する

手順1~5までをブロックプロデューサー用サーバーで実施してから、以下を実施します。

ブロックプロデューサーノードは、ブロック生成に必要なペアキー (cold keys, KES hot keys and VRF hot keys)を用いて起動します。リレーノードのみに接続します。

一方で、リレーノードはキーを所有していないため、ブロック生成はできません。その代わり、他のリレーノードとの繋がりを持ち最新スロットを取得します。

このマニュアルでは、2つのサーバー上に1ノードづつ構築します。1つのノードはブロックプロデューサーノード、もう1つのノードはリレーノード1という名前のリレーノードになります。

topology.json ファイルの構成について

  • リレーノードでは、パプリックノード (IOHKや他のリレーノード) 及び、自身の

    ブロックプロデューサーノード情報を記述します。

  • ブロックプロデューサーノードでは、自身のリレーノード情報のみ記述します。

自身のブロックプロデューサーノード上で以下のコマンドを実行します。 「addr」にはリレーノードのパプリックIPアドレスを記述します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cat > $NODE_HOME/${NODE_CONFIG}-topology.json << EOF
{
"Producers": [
{
"addr": "<リレーノード1のパブリックIPアドレス>",
"port": 6000,
"valency": 1
}
]
}
EOF

🔏 7. エアギャップオフラインマシンを構成する

エアギャップオフラインマシンは「コールド環境」と呼ばれ、インターネットに接続しない独立したオフライン環境のことです。

  • キーロギング攻撃、マルウエア/ウイルスベースの攻撃、その他ファイアウォールやセキュリティーの悪用から保護します。

  • 有線・無線のインターネットには接続しないでください。

  • ネットワーク上にあるVMマシンではありません。

  • エアギャップについて更に詳しく知りたい場合は、こちらを参照下さい。

エアギャップオフラインマシン上で手順1~2をセットアップした後、以下のパスを環境変数にセットします。

エアギャップオフラインマシン
エアギャップオフラインマシン
echo export NODE_HOME=$HOME/cardano-my-node >> $HOME/.bashrc
source $HOME/.bashrc
mkdir -p $NODE_HOME

最も安全な構成を維持するには、USBなどを利用してホット環境とコールド環境間でファイルを物理的に移動することが望ましいです。

⚙ 8. ブロックプロデューサーキーを生成する。

以下の項目を実施する前にノードが起動しているか確認してください。

tmux a -t cnode

ログが流れていればノードが起動しています。 Ctrl+B を押したあとにdを押すと前の画面に戻ります。

ブロックプロデューサーノードでは Shelley台帳仕様書で定義されている、3つのキーを生成する必要があります。

  • ステークプールのコールドキー (node.cert)

  • ステークプールのホットキー (kes.skey)

  • ステークプールのVRFキー (vrf.skey)

まずは、KESペアキーを作成します。 (KES=Key Evolving Signature)

ブロックプロデューサーノード
ブロックプロデューサーノード
cd $NODE_HOME
cardano-cli node key-gen-KES \
--verification-key-file kes.vkey \
--signing-key-file kes.skey

KESキーは、キーを悪用するハッカーからステークプールを保護するために作成され、90日ごとに再生成する必要があります。

🔥 コールドキーは常にエアギャップオフラインマシンで生成および保管する必要があります コールドキーは次のパスに格納されるようにします。 $HOME/cold-keys.

コールドキーを格納するディレクトリを作成します。

エアギャップオフラインマシン
エアギャップオフラインマシン
mkdir $HOME/cold-keys
pushd $HOME/cold-keys

コールドキーのペアキーとカウンターファイルを作成します。

エアギャップオフラインマシン
エアギャップオフラインマシン
cardano-cli node key-gen \
--cold-verification-key-file node.vkey \
--cold-signing-key-file node.skey \
--operational-certificate-issue-counter node.counter
chmod 400 node.vkey
chmod 400 node.skey

すべてのキーを別の安全なストレージデバイスにバックアップしましょう!複数のバックアップを作成することをおすすめします。

ジェネシスファイルからslotsPerKESPeriodを出力します。

続行する前に、ノードをブロックチェーンと完全に同期する必要があります。 同期が途中の場合、正しいslotsPerKESPeriodを取得できません。 あなたのノードが完全に同期されたことを確認するには、こちらのサイトhttps://pooltool.io/で自身の同期済みエポックとスロットが一致しているかをご確認ください。

ブロックプロデューサーノード
ブロックプロデューサーノード
pushd +1
slotsPerKESPeriod=$(cat $NODE_HOME/${NODE_CONFIG}-shelley-genesis.json | jq -r '.slotsPerKESPeriod')
echo slotsPerKESPeriod: ${slotsPerKESPeriod}
ブロックプロデューサーノード
ブロックプロデューサーノード
slotNo=$(cardano-cli query tip --mainnet | jq -r '.slotNo')
echo slotNo: ${slotNo}

スロット番号をslotsPerKESPeriodで割り、kesPeriodを算出します。

ブロックプロデューサーノード
ブロックプロデューサーノード
kesPeriod=$((${slotNo} / ${slotsPerKESPeriod}))
echo kesPeriod: ${kesPeriod}
startKesPeriod=${kesPeriod}
echo startKesPeriod: ${startKesPeriod}

これにより、プール運用証明書を生成することができます。

kes.vkey をエアギャップオフラインマシンのcardano-my-nodeディレクトリにコピーします。

バージョン 1.19.0ではstartKesPeriodの値を(kesPeriod-1)に設定する必要があります。

ステークプールオペレータは、プールを実行する権限があることを確認するための運用証明書を発行する必要があります。証明書には、オペレータの署名が含まれプールに関する情報(アドレス、キーなど)が含まれます。

<startKesPeriod>の部分を上記で算出した数値(startKesPeriodの値)に置き換えます。

エアギャップオフラインマシン
エアギャップオフラインマシン
cardano-cli node issue-op-cert \
--kes-verification-key-file kes.vkey \
--cold-signing-key-file $HOME/cold-keys/node.skey \
--operational-certificate-issue-counter $HOME/cold-keys/node.counter \
--kes-period <startKesPeriod> \
--out-file node.cert

node.cert をブロックプロデューサノードのcardano-my-nodeディレクトリにコピーします。

VRFペアキーを作成します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli node key-gen-VRF \
--verification-key-file vrf.vkey \
--signing-key-file vrf.skey

vrfキーのアクセス権を読み取り専用に更新します。

chmod 400 vrf.skey

次のコマンドを実行して一旦ノードを停止します。 (以下のコマンドは、8-1を実施している前提のコマンドです)

ブロックプロデューサーノード
ブロックプロデューサーノード
sudo systemctl stop cardano-node

起動スクリプトにKES、VRF、運用証明書のパスを追記し更新します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cat > $NODE_HOME/startBlockProducingNode.sh << EOF
DIRECTORY=\$NODE_HOME
PORT=6000
HOSTADDR=0.0.0.0
TOPOLOGY=\${DIRECTORY}/${NODE_CONFIG}-topology.json
DB_PATH=\${DIRECTORY}/db
SOCKET_PATH=\${DIRECTORY}/db/socket
CONFIG=\${DIRECTORY}/${NODE_CONFIG}-config.json
KES=\${DIRECTORY}/kes.skey
VRF=\${DIRECTORY}/vrf.skey
CERT=\${DIRECTORY}/node.cert
cardano-node run --topology \${TOPOLOGY} --database-path \${DB_PATH} --socket-path \${SOCKET_PATH} --host-addr \${HOSTADDR} --port \${PORT} --config \${CONFIG} --shelley-kes-key \${KES} --shelley-vrf-key \${VRF} --shelley-operational-certificate \${CERT}
EOF

ステークプールを運用するには、KES、VRFキー、および運用証明書が必要です。

ブロックプロデューサーノードを起動します。

ブロックプロデューサーノード
ブロックプロデューサーノード
sudo systemctl start cardano-node

🔐 9. 各種アドレス用のキーを作成します。(payment/stake用アドレス)

ステークプール登録後、やり直しは出来ません。

まずは、プロトコルパラメータを取得します。

このエラーが出た場合は、ノードが同期を開始するまで待つか、手順3に戻り「db/socket」へのパスが追加されているか確認してください。

cardano-cli: Network.Socket.connect: : does not exist (No such file or directory)

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli query protocol-parameters \
--mainnet \
--allegra-era \
--out-file params.json

paymentキーは支払い用アドレスに使用され、stakeキーはプール委任アドレス用の管理に使用されます。

🔥 運用上のセキュリティに関する重要なアドバス: キーの生成はエアギャップオフラインマシンで生成する必要があり、インターネット接続が無くても生成可能です。

ホット環境(オンライン)で必要とする手順は以下の内容のみです。

  • 現在のスロット番号を取得する

  • アドレスの残高を照会する

  • トランザクションの送信

Cardano-CLIを使用する方法
Cardano-CLIを使用する方法

支払い用アドレスのペアキーを作成します。: payment.skey & payment.vkey

###
### On エアギャップオフラインマシン,
###
cd $NODE_HOME
cardano-cli address key-gen \
--verification-key-file payment.vkey \
--signing-key-file payment.skey

ステークアドレス用のペアキーを作成します。 stake.skey & stake.vkey

###
### On エアギャップオフラインマシン,
###
cardano-cli stake-address key-gen \
--verification-key-file stake.vkey \
--signing-key-file stake.skey

ステークアドレス検証キーから、ステークアドレスファイルを作成します。 stake.addr

###
### On エアギャップオフラインマシン,
###
cardano-cli stake-address build \
--stake-verification-key-file stake.vkey \
--out-file stake.addr \
--mainnet

ステークアドレスに委任する支払い用アドレスを作成します。

###
### On エアギャップオフラインマシン,
###
cardano-cli address build \
--payment-verification-key-file payment.vkey \
--stake-verification-key-file stake.vkey \
--out-file payment.addr \
--mainnet

上書きされないようパーミッションを変更する。

###
### On エアギャップオフラインマシン,
###
chmod 400 payment.vkey
chmod 400 payment.skey
chmod 400 stake.vkey
chmod 400 stake.skey
chmod 400 stake.addr
chmod 400 payment.addr

※プール運営開始後に、上記の処理を実行するとアドレスが上書きされるので注意してください。

次のステップは、あなたの支払いアドレスに送金する手順です。

payment.addr をブロックプロデューサノードのcardano-my-nodeディレクトリにコピーします。

メインネット
メインネット候補版
Shelley テストネット
メインネット

以下のウォレットアドレスから送金が可能です。

  • ダイダロス / ヨロイウォレット

  • もしITNに参加している場合は、キーを変換できます。

次のコードを実行し。支払いアドレスを表示させ、このアドレスに送金します。

echo "$(cat payment.addr)"
メインネット候補版

以下のウォレットアドレスから送金が可能です。

  • バイロンメインネット資金

  • INTに参加している場合は、キーを変換できます。

次のコードを実行し。支払いアドレスを表示させます。

echo "$(cat payment.addr)"
Shelley テストネット

テストネット用口座にあなたの支払い用アドレスをリクエストします。

次のコードを実行し。支払いアドレスを表示させます。

echo "$(cat payment.addr)"

このアドレスを上記ページのリクエスト欄に貼り付けます。

シェリーテストネット用口座は24時間ごとに100,000fADAを提供します。

支払い用アドレスに送金後、残高を確認してください。

続行する前に、ノードをブロックチェーンと完全に同期させる必要があります。完全に同期されていない場合は、残高が表示されません。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli query utxo \
--address $(cat payment.addr) \
--mainnet \
--allegra-era

次のように表示されます。

TxHash TxIx Lovelace
----------------------------------------------------------------------------------------
100322a39d02c2ead.... 0 1000000000

👩 10. ステークアドレスを登録します。

ステークプール登録後、やり直しは出来ません。

stake.vkeyを使用して、stake.cert証明証を作成します。

エアギャップオフラインマシン
エアギャップオフラインマシン
cardano-cli stake-address registration-certificate \
--stake-verification-key-file stake.vkey \
--out-file stake.cert

stake.cert をブロックプロデューサーノードのcardano-my-nodeディレクトリにコピーします。 ttlパラメータを設定するには、最新のスロット番号を取得する必要があります。

ブロックプロデューサーノード
ブロックプロデューサーノード
currentSlot=$(cardano-cli query tip --mainnet | jq -r '.slotNo')
echo Current Slot: $currentSlot

残高とUTXOを出力します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli query utxo \
--address $(cat payment.addr) \
--mainnet \
--allegra-era > fullUtxo.out
tail -n +3 fullUtxo.out | sort -k3 -nr > balance.out
cat balance.out
tx_in=""
total_balance=0
while read -r utxo; do
in_addr=$(awk '{ print $1 }' <<< "${utxo}")
idx=$(awk '{ print $2 }' <<< "${utxo}")
utxo_balance=$(awk '{ print $3 }' <<< "${utxo}")
total_balance=$((${total_balance}+${utxo_balance}))
echo TxHash: ${in_addr}#${idx}
echo ADA: ${utxo_balance}
tx_in="${tx_in} --tx-in ${in_addr}#${idx}"
done < balance.out
txcnt=$(cat balance.out | wc -l)
echo Total ADA balance: ${total_balance}
echo Number of UTXOs: ${txcnt}

keyDepositの値を出力します。

ブロックプロデューサーノード
ブロックプロデューサーノード
keyDeposit=$(cat $NODE_HOME/params.json | jq -r '.keyDeposit')
echo keyDeposit: $keyDeposit

ステークアドレス証明書の登録には2,000,000 lovelace (2ADA)が必要です。

build-rawトランザクションコマンドを実行します。

invalid-hereafterの値は、現在のスロット番号よりも大きくなければなりません。この例では現在のスロット番号+10000を使用します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli transaction build-raw \
${tx_in} \
--tx-out $(cat payment.addr)+0 \
--invalid-hereafter $(( ${currentSlot} + 10000)) \
--fee 0 \
--out-file tx.tmp \
--allegra-era \
--certificate stake.cert

現在の最低手数料を計算します。

ブロックプロデューサーノード
ブロックプロデューサーノード
fee=$(cardano-cli transaction calculate-min-fee \
--tx-body-file tx.tmp \
--tx-in-count ${txcnt} \
--tx-out-count 1 \
--mainnet \
--witness-count 2 \
--byron-witness-count 0 \
--protocol-params-file params.json | awk '{ print $1 }')
echo fee: $fee

残高が、手数料+keyDepositの値よりも大きいことを確認してください。そうしないと機能しません。

計算結果を出力します。

ブロックプロデューサーノード
ブロックプロデューサーノード
txOut=$((${total_balance}-${keyDeposit}-${fee}))
echo Change Output: ${txOut}

ステークアドレスを登録するトランザクションファイルを作成します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli transaction build-raw \
${tx_in} \
--tx-out $(cat payment.addr)+${txOut} \
--invalid-hereafter $(( ${currentSlot} + 10000)) \
--fee ${fee} \
--certificate-file stake.cert \
--allegra-era \
--out-file tx.raw

tx.rawをエアギャップオフラインマシンのcardano-my-nodeディレクトリにコピーします。

paymentとstakeの秘密鍵でトランザクションファイルに署名します。

エアギャップオフラインマシン
エアギャップオフラインマシン
cardano-cli transaction sign \
--tx-body-file tx.raw \
--signing-key-file payment.skey \
--signing-key-file stake.skey \
--mainnet \
--out-file tx.signed

tx.signedをブロックプロデューサーノードcardano-my-nodeディレクトリにコピーします。

署名されたトランザクションを送信します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli transaction submit \
--tx-file tx.signed \
--mainnet

📄 11. ステークプールを登録します。

ステークプール登録には500ADAの登録料が必要です。 payment.addrに入金されている必要があります。

JSONファイルを作成してプールのメタデータを作成します。

ticker名の長さは3~5文字にする必要があります。文字はA-Zと0-9のみで構成する必要があります。

descriptionの長さは255文字以内となります。

ブロックプロデューサーノード
ブロックプロデューサーノード
cd $NODE_HOME
cat > poolMetaData.json << EOF
{
"name": "MyPoolName",
"description": "My pool description",
"ticker": "MPN",
"homepage": "https://myadapoolnamerocks.com"
}
EOF

メタデータファイルのハッシュ値を計算します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli stake-pool metadata-hash --pool-metadata-file poolMetaData.json > poolMetaDataHash.txt

poolMetaDataHash.txtをエアギャップオフラインマシンへコピーしてください poolMetaData.jsonをあなたの公開用WEBサーバへアップロードしてください。

最小プールコストを出力します。

ブロックプロデューサーノード
ブロックプロデューサーノード
minPoolCost=$(cat $NODE_HOME/params.json | jq -r .minPoolCost)
echo minPoolCost: ${minPoolCost}

minPoolCostは 340000000 lovelace (340 ADA)です。

ステークプールの登録証明書を作成します。 メタデータのURLリレーノード情報を追記し構成します。リレーノード構成にはDNSベースまたはIPベースのどちらかを選択できます。

metadata-urlは64文字以内とし、あなたの環境に合わせて修正してください。

ブロックプロデューサーノードにあるvrf.vkeyをエアギャップオフラインマシンcardano-my-nodeディレクトリにコピーします。

pool.certを作成する

エアギャップオフラインマシン
エアギャップオフラインマシン
cardano-cli stake-pool registration-certificate \
--cold-verification-key-file $HOME/cold-keys/node.vkey \
--vrf-verification-key-file vrf.vkey \
--pool-pledge 100000000 \
--pool-cost 345000000 \
--pool-margin 0.15 \
--pool-reward-account-verification-key-file stake.vkey \
--pool-owner-stake-verification-key-file stake.vkey \
--mainnet \
--single-host-pool-relay <dns based relay, example ~ relaynode1.myadapoolnamerocks.com> \
--pool-relay-port 6000 \
--metadata-url <poolMetaData.jsonをアップロードしたURLを記述> \
--metadata-hash $(cat poolMetaDataHash.txt) \
--out-file pool.cert

ここでは345ADAの固定費と15%のプールマージン、100ADAの誓約を設定しています。 ご自身の設定値に変更してください。

上記のpool.cert作成時、自身のリレー情報を以下の3パターンの記述方法があります。 ノード管理を簡単にするために、DNSベースのリレー設定をお勧めします。 もしリレーサーバを変更する場合、IPアドレスが変わるため、その都度登録証明書を再送する必要がありますがDNSベースで登録しておけば、IPアドレスが変更になってもお使いのドメイン管理画面にてIPアドレスを変更するだけで完了します。

****✨ 複数のリレーノードを構成する記述方法

DNSレコードに1つのエントリーの場合

--single-host-pool-relay <your first relay node address> \
--pool-relay-port 6000 \
--single-host-pool-relay <your Second relay node address> \
--pool-relay-port 6000 \

ラウンドロビンDNSベース SRV DNS recordの場合

--multi-host-pool-relay <your first relay node address> \
--pool-relay-port 6000 \

IPアドレス, 1ノード1IPアドレスの場合

--pool-relay-port 6000 \
--pool-relay-ipv4 <your first relay node public IP address> \
--pool-relay-port 6000 \
--pool-relay-ipv4 <your second relay node public IP address> \

ステークプールにステークを誓約するファイルを作成します。

エアギャップオフラインマシン
エアギャップオフラインマシン
cardano-cli stake-address delegation-certificate \
--stake-verification-key-file stake.vkey \
--cold-verification-key-file $HOME/cold-keys/node.vkey \
--out-file deleg.cert

pool.certdeleg.certをブロックプロデューサーノードcardano-my-nodeディレクトリにコピーします。

自分のプールに資金を預けることをPledge(誓約)と呼ばれます

  • あなたの支払い用アドレスの残高はPledge額よりも大きい必要があります。

  • 誓約金を宣言しても、実際にはどこにも移動されていません。payment.addrに残ったままです。

  • 誓約を行わないと、ブロック生成の機会を逃し委任者は報酬を得ることができません。

  • あなたの誓約金はブロックされません。いつでも自由に取り出せます。

ttlパラメータを設定するには、最新のスロット番号を取得する必要があります。

ブロックプロデューサーノード
ブロックプロデューサーノード
currentSlot=$(cardano-cli query tip --mainnet | jq -r '.slotNo')
echo Current Slot: $currentSlot

残高とUTXOsを出力します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli query utxo \
--address $(cat payment.addr) \
--mainnet \
--allegra-era > fullUtxo.out
tail -n +3 fullUtxo.out | sort -k3 -nr > balance.out
cat balance.out
tx_in=""
total_balance=0
while read -r utxo; do
in_addr=$(awk '{ print $1 }' <<< "${utxo}")
idx=$(awk '{ print $2 }' <<< "${utxo}")
utxo_balance=$(awk '{ print $3 }' <<< "${utxo}")
total_balance=$((${total_balance}+${utxo_balance}))
echo TxHash: ${in_addr}#${idx}
echo ADA: ${utxo_balance}
tx_in="${tx_in} --tx-in ${in_addr}#${idx}"
done < balance.out
txcnt=$(cat balance.out | wc -l)
echo Total ADA balance: ${total_balance}
echo Number of UTXOs: ${txcnt}

poolDepositを出力します。

ブロックプロデューサーノード
ブロックプロデューサーノード
poolDeposit=$(cat $NODE_HOME/params.json | jq -r '.poolDeposit')
echo poolDeposit: $poolDeposit

build-rawトランザクションコマンドを実行します。

invalid-hereafterの値は、現在のスロット番号よりも大きくなければなりません。この例では、現在のスロット+10000を使用します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli transaction build-raw \
${tx_in} \
--tx-out $(cat payment.addr)+$(( ${total_balance} - ${poolDeposit})) \
--invalid-hereafter $(( ${currentSlot} + 10000)) \
--fee 0 \
--certificate-file pool.cert \
--certificate-file deleg.cert \
--allegra-era \
--out-file tx.tmp

最低手数料を計算します。

ブロックプロデューサーノード
ブロックプロデューサーノード
fee=$(cardano-cli transaction calculate-min-fee \
--tx-body-file tx.tmp \
--tx-in-count ${txcnt} \
--tx-out-count 1 \
--mainnet \
--witness-count 3 \
--byron-witness-count 0 \
--protocol-params-file params.json | awk '{ print $1 }')
echo fee: $fee

payment.addrの残高が、手数料コスト+poolDeposit(500ADA)よりも大きいことを確認してください。小さい場合は機能しません。

計算結果を出力します。

ブロックプロデューサーノード
ブロックプロデューサーノード
txOut=$((${total_balance}-${poolDeposit}-${fee}))
echo txOut: ${txOut}

トランザクションファイルを作成します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli transaction build-raw \
${tx_in} \
--tx-out $(cat payment.addr)+${txOut} \
--invalid-hereafter $(( ${currentSlot} + 10000)) \
--fee ${fee} \
--certificate-file pool.cert \
--certificate-file deleg.cert \
--allegra-era \
--out-file tx.raw

tx.rawをエアギャップオフラインマシンのcardano-my-nodeディレクトリにコピーします。

トランザクションに署名します。

エアギャップオフラインマシン
エアギャップオフラインマシン
cardano-cli transaction sign \
--tx-body-file tx.raw \
--signing-key-file payment.skey \
--signing-key-file $HOME/cold-keys/node.skey \
--signing-key-file stake.skey \
--mainnet \
--out-file tx.signed

tx.signedブロックプロデューサーノードcardano-my-nodeディレクトリにコピーします。

トランザクションを送信します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli transaction submit \
--tx-file tx.signed \
--mainnet

🐣 12. ステークプールが機能しているか確認します。

ステークプールIDは以下のように出力できます。

エアギャップオフラインマシン
エアギャップオフラインマシン
cardano-cli stake-pool id --cold-verification-key-file $HOME/cold-keys/node.vkey --output-format hex > stakepoolid.txt
cat stakepoolid.txt

stakepoolid.txtをブロックプロデューサーノードcardano-my-nodeディレクトリにコピーします。

このファイルを用いて、自分のステークプールがブロックチェーンに登録されているか確認します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli query ledger-state --mainnet --allegra-era | grep publicKey | grep $(cat stakepoolid.txt)

文字列による戻り値が返ってきた場合は、正常に登録されています 👏

あなたのステークプールを次のサイトで確認することが出来ます。 https://pooltool.io/

⚙ 14. トポロジーファイルを構成する。

この項目はリレーノードで実施します

バージョン1.25.1ではP2P(ピア・ツー・ピア)ノードを自動検出しないため、手動でトポロジーを構成する必要があります。この手順をスキップすると生成したブロックがブロックチェーン外で孤立するため、必須の設定項目となります。

topologyUpdater.shで更新する場合
topologyUpdater.shで更新する場合

🚀 topologyUpdater.shを使用してリレーノードを公開する

この方法を提案して頂いた GROWPOOL および CNTOOLS Guild OPS へのクレジット表記。

ノード情報をトポロジーフェッチリストに公開するスクリプト「topologyUpdater.sh」を作成します。 10行目の"CHANGE ME"をリレーノードのIPアドレスに変えます。 ※26行目の"CHANGE ME"はそのままでお願いします。

以下コードをリレー用サーバで実施してください。

cat > $NODE_HOME/topologyUpdater.sh << EOF
#!/bin/bash
# shellcheck disable=SC2086,SC2034
USERNAME=$(whoami)
CNODE_PORT=6000 # 自身のリレーノードポート番号を記入
CNODE_HOSTNAME="CHANGE ME" # リレーノードのIPアドレスまたはDNSアドレスを記入
CNODE_BIN="/usr/local/bin"
CNODE_HOME=$NODE_HOME
CNODE_LOG_DIR="\${CNODE_HOME}/logs"
GENESIS_JSON="\${CNODE_HOME}/${NODE_CONFIG}-shelley-genesis.json"
NETWORKID=\$(jq -r .networkId \$GENESIS_JSON)
CNODE_VALENCY=1 # optional for multi-IP hostnames
NWMAGIC=\$(jq -r .networkMagic < \$GENESIS_JSON)
[[ "\${NETWORKID}" = "Mainnet" ]] && HASH_IDENTIFIER="--mainnet" || HASH_IDENTIFIER="--testnet-magic \${NWMAGIC}"
[[ "\${NWMAGIC}" = "764824073" ]] && NETWORK_IDENTIFIER="--mainnet" || NETWORK_IDENTIFIER="--testnet-magic \${NWMAGIC}"
export PATH="\${CNODE_BIN}:\${PATH}"
export CARDANO_NODE_SOCKET_PATH="\${CNODE_HOME}/db/socket"
blockNo=\$(/usr/local/bin/cardano-cli query tip \${NETWORK_IDENTIFIER} | jq -r .blockNo )
# Note:
# ノードをIPv4/IPv6デュアルスタックネットワーク構成で実行している場合
# IPv4で実行するには、以下の curl コマンドに -4 パラメータを追加してください (curl -4 -s ...)
if [ "\${CNODE_HOSTNAME}" != "CHANGE ME" ]; then
T_HOSTNAME="&hostname=\${CNODE_HOSTNAME}"
else
T_HOSTNAME=''
fi
if [ ! -d \${CNODE_LOG_DIR} ]; then
mkdir -p \${CNODE_LOG_DIR};
fi
curl -4 -s "https://api.clio.one/htopology/v1/?port=\${CNODE_PORT}&blockNo=\${blockNo}&valency=\${CNODE_VALENCY}&magic=\${NWMAGIC}\${T_HOSTNAME}" | tee -a \$CNODE_LOG_DIR/topologyUpdater_lastresult.json
EOF

権限を追加し、「topologyUpdater.sh」を実行します。

###
### On relaynode1
###
cd $NODE_HOME
chmod +x topologyUpdater.sh
./topologyUpdater.sh

topologyUpdater.shが正常に実行された場合、以下の形式が表示されます。

{ "resultcode": "201", "datetime":"2020-07-28 01:23:45", "clientIp": "1.2.3.4", "iptype": 4, "msg": "nice to meet you" }

スクリプトが実行されるたびに、$NODE_HOME/logsにログが作成されます。 ※topologyUpdater.shは1時間以内に2回以上実行しないで下さい。最悪の場合ブラックリストに追加されることがあります。

crontabジョブを追加し、「topologyUpdater.sh」が自動的に実行されるように設定します。

以下のコードは毎時22分に実行されるように指定しています。(上記スクリプトを実行した時間(分)より以前の分を指定して下さい。)

以下のコードは複数回実行しないで下さい。 複数回実行した場合、同じ時間に複数自動実行されるスケジュールが登録されてしまうので、ブラックリストに入ります。

###
### On relaynode1
###
cat > $NODE_HOME/crontab-fragment.txt << EOF
22 * * * * ${NODE_HOME}/topologyUpdater.sh
EOF
crontab -l | cat - crontab-fragment.txt >crontab.txt && crontab crontab.txt
rm crontab-fragment.txt

no crontab for ~~ というメッセージが表示されることがありますが、Cron初回設定時に表示されるメッセージとなりますので、問題ありません。

crontab -l

以下が返り値として表示されればOK。

"22 /home/*/cardano-my-node/topologyUpdater.sh"

4時間の間で4回スクリプトが実行された後に、ノードがオンライン状態で有ることが認められた場合にノードIPがトポロジーフェッチリストに登録されます。

トポロジーフェッチリストに登録されたか確認する

cd $NODE_HOME/logs
cat topologyUpdater_lastresult.json

以下の内容が表示されていれば登録成功 resultcodeが400番台・500番台の場合は、サーバ設定に問題があります。

{ "resultcode": "201", "datetime":"2021-01-10 18:30:06", "clientIp": "000.000.000.000", "iptype": 4, "msg": "nice to meet you" }
{ "resultcode": "203", "datetime":"2021-01-10 19:30:03", "clientIp": "000.000.000.000", "iptype": 4, "msg": "welcome to the topology" }
{ "resultcode": "204", "datetime":"2021-01-10 20:30:04", "clientIp": "000.000.000.000", "iptype": 4, "msg": "glad you're staying with us" }

🤹♀ リレーノードトポロジーファイルを更新する

リレーノードIPがトポロジーフェッチリストに登録されたことを確認後、以下のセクションを実行して下さい。

トポロジーファイルを更新するrelay-topology_pull.shスクリプトを作成します。 コマンドラインに送信する際に、自身のブロックプロデューサーのIPアドレスとポート番号に書き換えて下さい

※お知り合いのノードや自ノードが複数ある場合は、IOHKノード情報の後に "|" で区切ってIPアドレス:ポート番号:Valency の形式で追加できます。

###
### On relaynode1
###
cat > $NODE_HOME/relay-topology_pull.sh << EOF
#!/bin/bash
BLOCKPRODUCING_IP=<BLOCK PRODUCERS PUBLIC IP ADDRESS>
BLOCKPRODUCING_PORT=6000
curl -s -o $NODE_HOME/${NODE_CONFIG}-topology.json "https://api.clio.one/htopology/v1/fetch/?max=20&customPeers=\${BLOCKPRODUCING_IP}:\${BLOCKPRODUCING_PORT}:1|relays-new.cardano-mainnet.iohk.io:3001:2"
EOF

shファイルに権限を追加し実行します。

###
### On relaynode1
###
chmod +x relay-topology_pull.sh
./relay-topology_pull.sh

新しいトポロジーファイル(mainnet-topology.json)は、ステークプールを再起動した後に有効となります。

###
### On relaynode1
###
sudo systemctl reload-or-restart cardano-node

トポロジーファイルを更新した場合は、リレーノードを再起動することを忘れないで下さい。

****🔥 重要な確認事項: ブロックを生成するには、「TXs processed」が増加していることを確認する必要があります。万一、増加していない場合にはトポロジーファイルの内容を再確認して下さい。「peers」数はリレーノードが他ノードと接続している数を表しています。

🛠 gLiveView で確認

cd $NODE_HOME/scripts
./gLiveView.sh

「Txs processed」が増加しているか確認する

****🛑 注意事項r: ブロックプロデューサーノードを実行するためには、以下の3つのファイルが必要です。このファイルが揃っていない場合や起動時に指定されていない場合はブロックが生成できません。

###
### On ブロックプロデューサーノード
###
KES=\${DIRECTORY}/kes.skey
VRF=\${DIRECTORY}/vrf.skey
CERT=\${DIRECTORY}/node.cert

上記以外のキーファイルは、エアギャップオフライン環境で保管する必要があります

おめでとうございます!ステークプールが登録され、ブロックを作成する準備が出来ました。

🎇 15. ステークプール報酬を確認する

ブロックが正常に生成できた後、エポック終了後に報酬を確認しましょう!

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli query stake-address-info \
--address $(cat stake.addr) \
--mainnet \
--allegra-era

🔮 16. 監視ツール「Prometheus」および「Grafana Dashboard」のセットアップ

プロメテウスはターゲットに指定したメトリックHTTPエンドポイントをスクレイピングし、情報を収集する監視ツールです。オフィシャルドキュメントはこちら グラファナは収集されたデータを視覚的に表示させるダッシュボードツールです。

🐣 16.1 インストール

「prometheus」および「prometheus node exporter」をインストールします。 この手順では、リレーノード1でprometheusとGrafana本体を稼働させ、リレーノード1およびブロックプロデューサーノードの情報を取得する手順です。

リレーノード1
ブロックプロデューサーノード
リレーノード1
sudo apt-get install -y prometheus prometheus-node-exporter
ブロックプロデューサーノード
sudo apt-get install -y prometheus-node-exporter

grafanaをインストールします。

リレーノード1
リレーノード1
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
リレーノード1
リレーノード1
echo "deb https://packages.grafana.com/oss/deb stable main" > grafana.list
sudo mv grafana.list /etc/apt/sources.list.d/grafana.list
リレーノード1
リレーノード1
sudo apt-get update && sudo apt-get install -y grafana

サービスを有効にして、自動的に開始されるように設定します。

リレーノード1
ブロックプロデューサーノード
リレーノード1
sudo systemctl enable grafana-server.service
sudo systemctl enable prometheus.service
sudo systemctl enable prometheus-node-exporter.service
ブロックプロデューサーノード
sudo systemctl enable prometheus-node-exporter.service

/etc/prometheus/prometheus.yml に格納されている、「prometheus.yml」を更新します。

ご自身の<ブロックプロデューサーIPアドレス>に書き換えて、コマンドを送信してください。

リレーノード1
リレーノード1
cat > prometheus.yml << EOF
global:
scrape_interval: 15s # 15秒ごとに取得します
# Attach these labels to any time series or alerts when communicating with
# external systems (federation, remote storage, Alertmanager).
external_labels:
monitor: 'codelab-monitor'
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# The job name is added as a label job=<job_name> to any timeseries scraped from this config.
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9100']
- targets: ['<ブロックプロデューサーIPアドレス>:9100']
- targets: ['<ブロックプロデューサーIPアドレス>:12798']
labels:
alias: 'block-producing-node'
type: 'cardano-node'
- targets: ['localhost:12798']
labels:
alias: 'relaynode1'
type: 'cardano-node'
EOF
sudo mv prometheus.yml /etc/prometheus/prometheus.yml

サービスを起動します。

リレーノード1
リレーノード1
sudo systemctl restart grafana-server.service
sudo systemctl restart prometheus.service
sudo systemctl restart prometheus-node-exporter.service

サービスが正しく実行されていることを確認します。

リレーノード1
リレーノード1
sudo systemctl status grafana-server.service prometheus.service prometheus-node-exporter.service

${NODE_CONFIG}-config.jsonに新しい hasEKG情報と hasPrometheusポート情報を更新します。

ブロックプロデューサーノード
リレーノード1
ブロックプロデューサーノード
cd $NODE_HOME
sed -i ${NODE_CONFIG}-config.json -e "s/127.0.0.1/0.0.0.0/g"
リレーノード1
cd $NODE_HOME
sed -i ${NODE_CONFIG}-config.json -e "s/127.0.0.1/0.0.0.0/g"

ファイアウォールを設定している場合は、ブロックプロデューサーノードにて9100番と12798番ポートをリレーノードIP指定で開放して下さい。 リレーノード1では、Grafana用に3000番ポートを開放してください。

ステークプールを停止してスクリプトを再起動します。

ブロックプロデューサーノード
リレーノード1
ブロックプロデューサーノード
sudo systemctl reload-or-restart cardano-node
リレーノード1
sudo systemctl reload-or-restart cardano-node

📶 16.2 Grafanaダッシュボードの設定

  1. リレーノード1で、ローカルブラウザから http://localhost:3000 または http://<リレーノードIPアドレス>:3000 を開きます。 事前に 3000番ポートを開いておく必要があります。

  2. ログイン名・PWは次のとおりです。 admin / admin

  3. パスワードを変更します。

  4. 左メニューの歯車アイコンから データソースを追加します。

  5. 「Add data source」をクリックし、「Prometheus」を選択します。

  6. 名前は prometheus"としてください。

  7. URLhttp://localhost:9090に設定します。

  8. Save & Testをクリックします。

  9. 次のJSONファイルをダウンロードします。

  10. 左メニューからCreate + iconを選択 > Importをクリックします。

  11. 9でダウンロードしたJSONファイルをアップロードします。

  12. Importボタンをクリックします。

Grafana system health dashboard

おめでとうございます!これで基本的な設定は完了です。 次の項目は、運用中の便利なコマンドや保守のヒントが書かれています。

👏 17. 寄付とクレジット表記

このマニュアル制作に携わった全ての方に、感謝申し上げます。 快く翻訳を承諾して頂いた、CoinCashewには敬意を表します。 この活動をサポートして頂ける方は、是非寄付をよろしくお願い致します。

CoinCashew ADAアドレス

addr1qxhazv2dp8yvqwyxxlt7n7ufwhw582uqtcn9llqak736ptfyf8d2zwjceymcq6l5gxht0nx9zwazvtvnn22sl84tgkyq7guw7q

X StakePoolへの寄付

カルダノ分散化、日本コミュニティ発展の為に日本語化させて頂きました。私達をサポート頂ける方は当プールへ委任頂けますと幸いです。

  • Ticker:XSP

    Pool ID↓

    788898a81174665316af96880459dcca053f7825abb1b0db9a433630
  • ADAアドレス

    addr1q85kms3xw788pzxcr8g8d4umxjcr57w55k2gawnpwzklu97sc26z2lhct48alhew43ry674692u2eynccsyt9qexxsesjzz8qp

全ての協力者

  • 👏 Antonie of CNT for being awesomely helpful with Youtube content and in telegram.

  • 👏 Special thanks to Kaze-Stake for the pull requests and automatic script contributions.

  • 👏 The Legend of ₳da [TLOA] for translating this guide to Spanish.

  • 👏 X-StakePool [BTBF] for translating this guide to Japanese.

  • 👏 Chris of OMEGA | CODEX for security improvements.

  • 👏 Raymond of GROW for topologyUpdater improvements and being awesome.

🛠 18. プール運用とメンテナンス

🤖 18.1 新しいkesPeriodで運用証明書を更新する

ホットキーの有効期限が切れると、ホットキーを再作成し新しい運用証明書を発行する必要があります。

kesPeriodの更新: 新しい運用証明書を発行するときは、次を実行して「startKesPeriod」を見つけます

ブロックプロデューサーノード
ブロックプロデューサーノード
cd $NODE_HOME
slotNo=$(cardano-cli query tip --mainnet | jq -r '.slotNo')
slotsPerKESPeriod=$(cat $NODE_HOME/${NODE_CONFIG}-shelley-genesis.json | jq -r '.slotsPerKESPeriod')
kesPeriod=$((${slotNo} / ${slotsPerKESPeriod}))
startKesPeriod=${kesPeriod}
echo startKesPeriod: ${startKesPeriod}
ブロックプロデューサーノード
ブロックプロデューサーノード
cd $NODE_HOME
cardano-cli node key-gen-KES \
--verification-key-file kes.vkey \
--signing-key-file kes.skey

kes.vkeyをエアギャップオフラインマシンのcardano-my-nodeディレクトリにコピーします。

次のコマンドで、新しい node.certファイルを作成します。このときstartKesPeriodの値を下記の<startKesPeriod>の箇所に置き換えてからコマンドを送信してください。

<startKesPeriod>の部分を上記で算出した数値(startKesPeriodの値)に置き換えます。

エアギャップオフラインマシン
エアギャップオフラインマシン
cd $NODE_HOME
chmod u+rwx $HOME/cold-keys
cardano-cli node issue-op-cert \
--kes-verification-key-file kes.vkey \
--cold-signing-key-file $HOME/cold-keys/node.skey \
--operational-certificate-issue-counter $HOME/cold-keys/node.counter \
--kes-period <startKesPeriod> \
--out-file node.cert
chmod a-rwx $HOME/cold-keys

node.cert をブロックプロデューサーノードのcardano-my-nodeディレクトリにコピーします。

この手順を完了するには、ブロックプロデューサーノードを停止して再起動します。

ブロックプロデューサーノードsystemctl
ブロックプロデューサーノードsystemctl
sudo systemctl reload-or-restart cardano-node

●ブロックログを導入している場合は、各種サービスを再起動してください

sudo systemctl reload-or-restart cnode-cncli-sync.service
sudo systemctl reload-or-restart cnode-cncli-validate.service
sudo systemctl reload-or-restart cnode-cncli-leaderlog.service
sudo systemctl reload-or-restart cnode-logmonitor.service

****✨ ヒント: ホットキーを作成したら、コールドキーへのアクセス件を変更しセキュリティを向上させることができます。これによって誤削除、誤った編集などから保護できます。

ロックするには

chmod a-rwx $HOME/cold-keys

ロックを解除するには

chmod u+rwx $HOME/cold-keys

🔥 18.2 インストールのリセット

もう一度はじめからやり直したいですか?次の方法でやり直すことができます。

git repoを削除してから $NODE_HOMEcold-keys ディレクトリの名前を変更します (またはオプションで削除します)

rm -rf $HOME/git/cardano-node/ $HOME/git/libsodium/
mv $NODE_HOME $(basename $NODE_HOME)_backup_$(date -I)
mv $HOME/cold-keys $HOME/cold-keys_backup_$(date -I)

🌊 18.3 データベースのリセット

ブロックチェーンファイルの破損やノードがスタックして動かない場合、dbファイルを削除することで初めから同期をやり直すことができます。

cd $NODE_HOME
rm -rf db

📝 18.4 プールメタ情報、誓約や固定費、Marginの変更手順

誓約、固定費、Margin、リレー情報、メタ情報を変更する場合は、登録証明書の再送を行います。

minPoolCostを出力します。

ブロックプロデューサーノード
ブロックプロデューサーノード
minPoolCost=$(cat $NODE_HOME/params.json | jq -r .minPoolCost)
echo minPoolCost: ${minPoolCost}

minPoolCost は340000000 lovelace (340 ADA)です。 --pool-costは最低でもこの値以上に指定します。

poolMetaData.jsonを変更する場合は、メタデータファイルのハッシュを再計算し、更新されたpoolMetaData.jsonをWEBサーバへアップロードしてください。 詳細については 項目9を参照して下さい。

ブロックプロデューサーノード
ブロックプロデューサーノード
cd $NODE_HOME
cardano-cli stake-pool metadata-hash --pool-metadata-file poolMetaData.json > poolMetaDataHash.txt

登録証明書トランザクションを作成します。

複数のリレーノードを設定する場合は 項目12 を参考にパラメーターを指定して下さい。

poolMetaDataHash.txt をエアギャップオフラインマシンのcardano-my-nodeディレクトリにコピーします。

metadata-urlは64文字以下にする必要があります。

エアギャップオフラインマシン
エアギャップオフラインマシン
cd $NODE_HOME
cardano-cli stake-pool registration-certificate \
--cold-verification-key-file $HOME/cold-keys/node.vkey \
--vrf-verification-key-file vrf.vkey \
--pool-pledge 1000000000 \
--pool-cost 345000000 \
--pool-margin 0.20 \
--pool-reward-account-verification-key-file stake.vkey \
--pool-owner-stake-verification-key-file stake.vkey \
--mainnet \
--single-host-pool-relay <dns based relay, example ~ relaynode1.myadapoolnamerocks.com> \
--pool-relay-port 6000 \
--metadata-url <url where you uploaded poolMetaData.json> \
--metadata-hash $(cat poolMetaDataHash.txt) \
--out-file pool.cert

この例では345ADAの固定費と20%のMrgin、1000ADAを誓約しています。

ステークプールに誓約します。

エアギャップオフラインマシン
エアギャップオフラインマシン
cardano-cli stake-address delegation-certificate \
--stake-verification-key-file stake.vkey \
--cold-verification-key-file $HOME/cold-keys/node.vkey \
--out-file deleg.cert

pool.certdeleg.cert をブロックプロデューサーのcardano-my-nodeディレクトリにコピーします。

ttlパラメータを設定するには、最新のスロット番号を取得する必要があります。

ブロックプロデューサーノード
ブロックプロデューサーノード
currentSlot=$(cardano-cli query tip --mainnet | jq -r '.slotNo')
echo Current Slot: $currentSlot

残高と UTXOsを出力します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli query utxo \
--address $(cat payment.addr) \
--mainnet \
--allegra-era > fullUtxo.out
tail -n +3 fullUtxo.out | sort -k3 -nr > balance.out
cat balance.out
tx_in=""
total_balance=0
while read -r utxo; do
in_addr=$(awk '{ print $1 }' <<< "${utxo}")
idx=$(awk '{ print $2 }' <<< "${utxo}")
utxo_balance=$(awk '{ print $3 }' <<< "${utxo}")
total_balance=$((${total_balance}+${utxo_balance}))
echo TxHash: ${in_addr}#${idx}
echo ADA: ${utxo_balance}
tx_in="${tx_in} --tx-in ${in_addr}#${idx}"
done < balance.out
txcnt=$(cat balance.out | wc -l)
echo Total ADA balance: ${total_balance}
echo Number of UTXOs: ${txcnt}

build-rawトランザクションコマンドを実行します。

ttlの値は、現在のスロット番号よりも大きくなければいけません。この例では現在のスロット番号+10000で設定しています。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli transaction build-raw \
${tx_in} \
--tx-out $(cat payment.addr)+${total_balance} \
--invalid-hereafter $(( ${currentSlot} + 10000)) \
--fee 0 \
--certificate-file pool.cert \
--certificate-file deleg.cert \
--allegra-era \
--out-file tx.tmp

最低手数料を計算します。

ブロックプロデューサーノード
ブロックプロデューサーノード
fee=$(cardano-cli transaction calculate-min-fee \
--tx-body-file tx.tmp \
--tx-in-count ${txcnt} \
--tx-out-count 1 \
--mainnet \
--witness-count 3 \
--byron-witness-count 0 \
--protocol-params-file params.json | awk '{ print $1 }')
echo fee: $fee

計算結果を出力します。

ブロックプロデューサーノード
ブロックプロデューサーノード
txOut=$((${total_balance}-${fee}))
echo txOut: ${txOut}

トランザクションファイルを構築します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli transaction build-raw \
${tx_in} \
--tx-out $(cat payment.addr)+${txOut} \
--invalid-hereafter $(( ${currentSlot} + 10000)) \
--fee ${fee} \
--certificate-file pool.cert \
--certificate-file deleg.cert \
--allegra-era \
--out-file tx.raw

tx.raw をエアギャップオフラインマシンのcardano-my-nodeディレクトリにコピーします。

トランザクションに署名します。

エアギャップオフラインマシン
エアギャップオフラインマシン
cardano-cli transaction sign \
--tx-body-file tx.raw \
--signing-key-file payment.skey \
--signing-key-file $HOME/cold-keys/node.skey \
--signing-key-file stake.skey \
--mainnet \
--out-file tx.signed

tx.signedををブロックプロデューサーノードのcardano-my-nodeディレクトリにコピーします。

トランザクションを送信します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli transaction submit \
--tx-file tx.signed \
--mainnet

変更は次のエポックで有効になります。次のエポック移行後にプール設定が正しいことを確認してください。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli query ledger-state --mainnet --allegra-era --out-file ledger-state.json
jq -r '.esLState._delegationState._pstate._pParams."'"$(cat stakepoolid.txt)"'" // empty' ledger-state.json

🧩 18.5 SSHを介したファイルの転送

一般的な使用例

  • stake/paymentキーのバックアップをダウンロードする

  • オフラインノードからブロックプロデューサーへ新しいファイルをアップロードする。

ノードからローカルPCにファイルをダウンロードする方法

ssh <USERNAME>@<IP ADDRESS> -p <SSH-PORT>
rsync -avzhe “ssh -p <SSH-PORT><USERNAME>@<IP ADDRESS>:<PATH TO NODE DESTINATION> <PATH TO LOCAL PC DESTINATION>

例:

ssh myusername@6.1.2.3 -p 12345

rsync -avzhe "ssh -p 12345" myusername@6.1.2.3:/home/myusername/cardano-my-node/stake.vkey ./stake.vkey

ローカルPCからノードにファイルをアップロードする方法

ssh <USERNAME>@<IP ADDRESS> -p <SSH-PORT>
rsync -avzhe “ssh -p <SSH-PORT><PATH TO LOCAL PC DESTINATION> <USERNAME>@<IP ADDRESS>:<PATH TO NODE DESTINATION>

例:

ssh myusername@6.1.2.3 -p 12345

rsync -avzhe "ssh -p 12345" ./node.cert myusername@6.1.2.3:/home/myusername/cardano-my-node/node.cert

✅ 18.7 ITNキーでステークプールティッカーを確認する。

信頼できるステークプールのなりすましや、プール運営を悪用する人から身を守るために、所有者はITNステークプールの所有権を証明することでティッカーを証明できます。

ITNのバイナリファイルが$NODE_HOMEにあることを確認して下さい。 itn_owner.skeyはステークプールIDに署名するために使用されています。

エアギャップオフラインマシン
エアギャップオフラインマシン
./jcli key sign --secret-key itn_owner.skey stakepoolid.txt --output stakepoolid.sig

次のコマンドでプールIDを確認します。

エアギャップオフラインマシン
エアギャップオフラインマシン
cat stakepoolid.sig

ITNで作成したファイルで、所有者の公開鍵を見つけます。このデータは末尾が「.pub」で保存されている可能性があります。

📚 18.8 ノードの構成ファイル更新

最新の.jsonファイルをダウンロードして、構成ファイルを最新の状態に保ちます。

NODE_BUILD_NUM=$(curl https://hydra.iohk.io/job/Cardano/iohk-nix/cardano-deployment/latest-finished/download/1/index.html | grep -e "build" | sed 's/.*build\/\([0-9]*\)\/download.*/\1/g')
cd $NODE_HOME
wget -N https://hydra.iohk.io/build/${NODE_BUILD_NUM}/download/1/${NODE_CONFIG}-byron-genesis.json
wget -N https://hydra.iohk.io/build/${NODE_BUILD_NUM}/download/1/${NODE_CONFIG}-shelley-genesis.json
wget -N https://hydra.iohk.io/build/${NODE_BUILD_NUM}/download/1/${NODE_CONFIG}-config.json
sed -i ${NODE_CONFIG}-config.json \
-e "s/TraceBlockFetchDecisions\": false/TraceBlockFetchDecisions\": true/g" \
-e "s/127.0.0.1/0.0.0.0/g"

💸 18.9 簡単なトランザクション送信の例をご紹介します

10 ADA を payment.addrから自分のアドレスへ送信する例です 🙃

まずは、最新のスロット番号を取得し invalid-hereafter パラメータを正しく設定します。

ブロックプロデューサーノード
ブロックプロデューサーノード
currentSlot=$(cardano-cli query tip --mainnet | jq -r '.slotNo')
echo Current Slot: $currentSlot

lovelaces形式で送信する金額を設定します。. ✨ 1 ADA = 1,000,000 lovelaces で覚えます。

ブロックプロデューサーノード
ブロックプロデューサーノード
amountToSend=10000000
echo amountToSend: $amountToSend

送金先のアドレスを設定します。

ブロックプロデューサーノード
ブロックプロデューサーノード
destinationAddress=<送金先アドレス>
echo destinationAddress: $destinationAddress

残高と UTXOsを出力します。

ブロックプロデューサーノード
ブロックプロデューサーノード
cardano-cli query utxo \
--address $(cat payment.addr) \
--mainnet \
--allegra-era > fullUtxo.out