シンボルノードを Symbol-Shoestring PyPIで構築

23 9月 2025

SYMBOL-SHOESTRING で新規ノード作成

概要

symbol-shoestring は、Symbol blockchain ネットワークのノード導入・運用、設定ファイルや証明書(CA 鍵や証明書など)の管理を補助するツールです。
特に、ノードの起動初期に必要な鍵・証明書の生成・管理を簡単にすることを目的としています。

前提条件

  • Python バージョン: 3.9.2 以上、4.0.0 未満
  • OpenSSL 等の外部コマンド(秘密鍵の生成や PEM の確認に使用)を利用可能であること。

インストール

  1. PyPI からインストールする方法
    python3 -m pip install symbol-shoestring==0.2.2

基本的な使い方(コマンドとオプション)

コマンド 主な用途 主なオプション/引数
init shoestring のテンプレート構成ファイルを抽出し、カスタマイズ可能な設定ファイルを準備する --package PACKAGE(ネットワーク構成パッケージ指定。
例:mainnet や sai(testnet)) 
pemtool 主秘密鍵 PEM ファイルを生成、場合により既存鍵の取り込みや暗号化を行う --output OUTPUT(出力先) 
--input INPUT(既存鍵取り込みオプション) 
--ask-pass(暗号化 PEM を生成するためパスワード入力) 
--force(既存の出力先ファイルを上書き) 
setup 新しいノードをゼロから構築する --config CONFIG(設定ファイル) 
--ca-key-path CA_KEY_PATH(メイン秘密鍵のパス) 
--package PACKAGE 
--directory DIRECTORY 
--security {default,paranoid,insecure} など 
renew-certificates ノード証明書の更新を行う --renew-ca(CA 証明書も更新するか) 
--retain-node-key(既存ノード鍵を保持するか) 
renew-voting-keys 投票鍵の更新 — 
signer / announce-transaction トランザクションの署名とネットワークへの発表 --transaction 引数など 

(その他、証明書チェーンの指定やノード識別子、証明書有効期間などのオプションがあるので、実際の githubリポジトリ READMEPyPI サイトを参照してください)
 

設定ファイル(INI形式)について

Shoestring の設定は .ini ファイルで行われます。主要なセクションと設定項目は次の通りです。運用時に必ず確認してください。

セクション 主な内容
network ネットワーク名、識別子 (identifier)、epochAdjustment、generationHashSeed など。ネットワーク設定パッケージ (package) によって提供される値と一致させる必要あり。 
images 使用する Docker イメージ(例:クライアント、REST サービス等) 
services ノードに関係する補助サービス(例:nodewatch など) 
transactions 手数料倍率 (feeMultiplier)、タイムアウト、最小署名数などトランザクション生成に関する設定 
imports ハーベスター鍵・投票鍵など、既存の鍵を取り込むための設定パス 
node ノードの機能 (features)、ユーザー/グループ識別、証明書共通名 (common name) や CA/ノード証明書に関する設定、CA 鍵のパスワード設定など 

また、「overrides」「rest-overrides」というカスタマイズ用の設定ファイルもあり、標準設定に対して上書きや追加設定を行うために用います。

 

セキュリティに関する注意事項

  1. 暗号化されていない PEM ファイルの取り扱い
    デフォルトでは暗号化されていない PEM ファイルが出力されます。これには秘密鍵が含まれるため、十分注意して管理してください。
  2. 暗号化 PEM ファイルの利用
    pemtool を使うことで暗号化された PEM ファイルを生成できます。もし秘密鍵の価値・重要性が高いなら、こちらの使用を強く推奨します。
  3. CA 秘密鍵(例:ca.key.pem)のバックアップ
    ファイルを削除する前には必ずバックアップをとっておいてください。失われると復元できない場合があります。
  4. ノード設定完了後の秘密鍵の削除
    ノードが適切に設定されて正常に稼働していることを確認したら、不要になった秘密鍵ファイルを削除してください。

 

セットアップ手順例 pip(ubuntu)

必要依存をインストールする

  • 作業環境構築
    $ sudo apt install python3 python3-pip openssl
    $ mkdir ~/symbol-testnet
    $ cd ~/symbol-testnet
  • 仮想環境を作成
    $ python3 -m venv ~/venv/shoestring
  • 有効化
    $ source ~/venv/shoestring/bin/activate
  • インストール
    (shoestring) ubuntu@:~/symbol-testnet $ pip install symbol-shoestring==0.2.2
  • 実行(モジュール形式)
    (shoestring) ubuntu@:~/symbol-testnet $ python3 -m shoestring --help

鍵を生成する

ノードを新規で立ち上げる場合(新しい CA 鍵をランダム生成)
$ openssl genpkey -algorithm ed25519 -out ca.key.pem 

/***
暗号化ファイルの場合
$ openssl genpkey -algorithm ed25519 -out ca.key.pem -aes-256-cbc -pass pass:MySecretPassword

(新規 CA 鍵を作って暗号化 PEM 化)
1) 32バイトの秘密鍵をランダム生成(16進64桁)
$ openssl rand -hex 32 > ca.key.hex
長さチェック(64桁であること)
$ test "$(tr -d '\n\r' < ca.key.hex | wc -c)" -eq 64 && echo "OK (64 hex chars)" || echo "BAD LENGTH"
2) 暗号化付きで PEM に変換
$ python3 -m shoestring pemtool --input ca.key.hex --output ca.key.pem --ask-pass

bash でのコマンド履歴削除
$ history -c
$ history -w
$ unset HISTFILE
$ > ~/.bash_history
***/

ノード構成ファイルを設定する

テストネット用(sai) 設定ファイル生成
$ python3 -m shoestring init --package sai config.ini

$ vi config.ini
-----
[network]
name = testnet
identifier = 152
epochAdjustment = 1667250467
generationHashSeed = 49D6E1CE276A85B70EAFE52349AACCA389302E7A9754BCF1221E79494FC665A4

[images]
client = symbolplatform/symbol-server:gcc-1.0.3.9
rest = symbolplatform/symbol-rest:2.5.1
mongo = mongo:7.0.23

[services]
nodewatch = https://nodewatch.symbol.tools/testnet

[transaction]
feeMultiplier = 200
timeoutHours = 1
minCosignaturesCount = 0
hashLockDuration = 1440
currencyMosaicId = 0x72C0212E67A08BCE
lockedFundsPerAggregate = 10000000

[imports]
harvester =
voter =
nodeKey =

[node]
features = API | HARVESTER
userId = 1000
groupId = 1000
caPassword =
apiHttps = true
lightApi = false

caCommonName = test CA
nodeCommonName = symboltestnet.u2yasan.com
 -----

カスタム設定は overrides.ini で行う
セクションの書き方は [<config-short-name>.<config-section>]

$ vi overrides.ini
-----
[user.account] 
enableDelegatedHarvestersAutoDetection = true 

[harvesting.harvesting] 
maxUnlockedAccounts = 5 
beneficiaryAddress = 

[node.node] 
minFeeMultiplier = 100 

[node.localnode] 
host = symboltestnet.u2yasan.com
friendlyName = U2YASAN
-----

$ python3 -m shoestring setup \
  --config config.ini \
  --package sai \
  --overrides overrides.ini \
  --directory ~/symbol-testnet \
  --ca-key-path ~/symbol-testnet/ca.key.pem

ノードを起動し、正常に動作していることを確認する

$ docker compose up -d

ヘルスチェック
$ python3 -m shoestring health \
  --config config.ini \
  --directory ~/symbol-testnet

以下のように立ち上がっていればOK
$ docker ps
IMAGE    PORTS    NAMES
mongo:7.0.23    27017/tcp    symbol-testnet-initiate-1
symbolplatform/symbol-server:gcc-1.0.3.9    0.0.0.0:7900->7900/tcp, :::7900->7900/tcp    symbol-testnet-client-1
mongo:7.0.23    127.0.0.1:27017->27017/tcp.   symbol-testnet-db-1
symbolplatform/symbol-rest:2.5.1    0.0.0.0:3000->3000/tcp, :::3000->3000/tcp   symbol-testnet-rest-api-1
symbolplatform/symbol-server:gcc-1.0.3.9    symbol-testnet-broker-1
 

起動確認後、ca.key.pem(秘密鍵)を削除する
(バックアップを確実に)

$ rm ~/symbol-testnet/ca.key.pem

ノードをハーベスティング可能な状態にする

$ python3 -m shoestring announce-transaction --config config.ini --transaction linking_transaction.dat

設定ファイルを変更した場合

アップグレード
$ python3 -m shoestring upgrade \
  --config config.ini \
  --overrides overrides.ini \
  --directory ~/symbol-testnet

 

その他

ca.key.pem PEMをデコードしてSymbolノードメイン秘密鍵を取得

python3 << 'EOF'
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
import getpass

# PEMファイルを読み込む
pem_file = 'ca.key.pem'
with open(pem_file, 'rb') as f:
   pem_data = f.read()

# パスワードの取得
password = None
try:
   # まず暗号化なしで試行
   private_key = serialization.load_pem_private_key(
       pem_data,
       password=None,
       backend=default_backend()
   )
   print("暗号化なしのPEMファイルです")
except TypeError:
   # 暗号化されている場合、パスワードを要求
   print("暗号化されたPEMファイルです")
   password_str = getpass.getpass("パスワードを入力してください: ")
   password = password_str.encode() if password_str else None
   
   private_key = serialization.load_pem_private_key(
       pem_data,
       password=password,
       backend=default_backend()
   )

# 秘密鍵の生データを取得
private_bytes = private_key.private_bytes(
   encoding=serialization.Encoding.Raw,
   format=serialization.PrivateFormat.Raw,
   encryption_algorithm=serialization.NoEncryption()
)

print(f"\n秘密鍵(16進数): {private_bytes.hex()}")
print(f"長さ: {len(private_bytes.hex())} 文字")
EOF

 

ハーベスト設定

setup コマンドで生成される

linking_transaction.dat

このトランザクションは、以下の3つのリンク操作を行います:

  1. Account Key Link - harvester鍵をメインアカウントにリンク
  2. VRF Key Link - VRF鍵をメインアカウントにリンク
  3. Voting Key Link - 投票鍵をメインアカウントにリンク

signatureが0000....の場合は署名し直し

 i     | transaction file written to /home/ubuntu/symbol-testnet/linking_transaction.dat      i     | ((signature: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, signer_public_key: 

ノードメインアカウントへ手数料分のXYMを送金して、アカウントをブロックチェーン上に認識させる

(shoestring) ubuntu@:~/symbol-testnet $ python3 -m shoestring signer --config config.ini --ca-key-path ca.key.pem linking_transaction.dat --save
 

(shoestring) ubuntu@:~/symbol-testnet $ python3 -m shoestring announce-transaction --config config.ini --transaction linking_transaction.dat

 i     | connecting to https://sym-test-01.opening-line.jp:3001      i     | preparing to announce transaction 3094A98F46D21BB6AE569D0279D33DB2F289E148EDB3A749924C1687AD9A0786 of type TransactionType.AGGREGATE_COMPLETE      i     | transaction was successfully sent to the network

トランザクションが取り込まれない場合
# REST APIでトランザクション状態を確認 
$ curl https://sym-test-01.opening-line.jp:3001/transactionStatus/3094A98F46D2…
# アカウント情報を取得 
$ curl https://sym-test-01.opening-line.jp:3001/accounts/TATTWZGULPA3IQTH6SF7G…

 

トラブルシューティング/よくある問題

  • 証明書の形式が不正
    PEM フォーマットの開始・終了行(-----BEGIN …/-----END …)が欠けていないかを確認。
  • パスワード入力を求められるが対応できない
    暗号化 PEM を使いたくても、shoestring wizard がパスワード入力非対応なので、暗号化ファイルを使う場合はその点を考慮。
  • 鍵・証明書の有効期間の設定ミス
    有効期限を短すぎまたは長すぎに設定しないよう、仕様に合わせて正しい期間を設定してください。

 

メインネットのデータ同期最新版は以下より取得可能
展開したdata, dbdata を置き換える
dual: https://catapultmainnetdata.s3.us-west-2.amazonaws.com/weekly/catapult_dual_data.tar.gz 
peer: https://catapultmainnetdata.s3.us-west-2.amazonaws.com/weekly/catapult_peer_data.tar.gz