XRP Ledger(XRPL)は、分散型台帳技術(Distributed Ledger Technology)を用いた高速かつ低コストの送金ネットワークです。
この記事では、XRPL.orgのXRP Ledger 開発者向けリソースドキュメント インフラストラクチャページのスタンドアロンモードでrippledをテストに従って、プライベートネットワークをDockerで構築しています。
プライベートネットワークとは?
プライベートネットワークとは、公式のメインネットとは切り離され、自分のPC上だけで動作する閉じたXRPL環境です。
- テスト用XRP:実際の価値はなく、自由に発行・送金できます。
- 利点:本番ネットワークに影響を与えず、機能検証や開発に集中可能です。
Dockerとは?
Dockerとは、アプリケーションを「コンテナ」という軽量な仮想環境で実行する仕組みです。
- 各アプリケーションを独立して実行可能
- 複数のXRPLノード(
rippled)を簡単に立ち上げられる - 設定の再現性が高く、テスト環境の自動構築にも最適
作成するネットワーク
このチュートリアルでは、以下のように3台のバリデータノード(Validator)が相互接続されたプライベートネットワークを作成します。

ノード構成
| ノード名 | 主な機能 |
|---|---|
| Validator-1 | ジェネシスウォレット保有(初期XRP配布の中心) |
| Validator-2 | Validator-1を信頼し、検証に参加するノード |
| Validator-3 | Validator-1を信頼し、検証に参加するノード |
用語補足
- バリデータノード(Validator):台帳の正しさを検証・合意形成に関わるサーバー
- ジェネシスウォレット:最初に大量のXRPを保有するアカウント
- Peer接続:ノード同士が通信するための接続関係
テスト用XRPと手数料(Fee)の扱い
このネットワークでは、実際のXRPではなくテスト用XRP(価値のない仮想XRP)を使用します。
- 初期配布:ジェネシスアカウントに大量に配布される
- Fee(手数料):トランザクションごとにごく少額(デフォルトで10 drops = 0.00001 XRP)が発生
- drop(ドロップ):XRPの最小単位(1 XRP = 1,000,000 drops)
設定ファイル(rippled.cfg)でこのFeeの値を変更することも可能です。
プライベートネットワークの構築
ここから、Docker Compose を用いて実際にプライベートネットワークを構築していきます。
作業ディレクトリの作成
#バリデータノードvalidator-1 validator-2 validator-3用に作業ディレクトリを作成する。
mkdir xrpl-private-network
cd xrpl-private-network
mkdir validator-1 validator-2 validator-3
ディレクトリ構成
xrpl-private-network
├── validator-1
├── validator-2
└── validator-3
バリデータキーペアの生成
バリデータとしてネットワークに参加するためのキーペアを、ローカル環境に生成します。
公式の XRPL4J ツールの rippledが使えるDocker コンテナのxrpllabs/xrpl4jを起動して、バリデータ鍵ペアを生成するためにコンテナ内でrippled validator-keys create_keysコマンドを実行する。
# validator-1のバリデータ鍵ペアを生成するコマンド
docker run --rm \
-v "$PWD/validator-1":/root/.ripple \
--entrypoint /opt/ripple/bin/validator-keys \
xrpllabsofficial/xrpld:latest \
create_keys
#ターミナルメッセージ
xrpllabsofficial/xrpld:latestイメージが、ローカルに無いためDocker Hubからダウンロードしてから、rippled validator-keys create_keysコマンドを実行して、バリデータ鍵ペアを生成。
Unable to find image 'xrpllabsofficial/xrpld:latest' locally
latest: Pulling from xrpllabsofficial/xrpld
312dda0739a2: Pull complete
d100128a81a6: Pull complete
0ed828415ce4: Pull complete
4f4fb700ef54: Pull complete
Digest: sha256:1b636a71bccf7b08b3771db9c9c98d6e7f74d88ff4d88267b5d9b4afb3190d96
Status: Downloaded newer image for xrpllabsofficial/xrpld:latest
Loading: "/etc/opt/ripple/rippled.cfg"
Validator keys stored in /root/.ripple/validator-keys.json
This file should be stored securely and not shared.
# validator-2のバリデータ鍵ペアを生成するコマンド
docker run --rm \
-v "$PWD/validator-2":/root/.ripple \
--entrypoint /opt/ripple/bin/validator-keys \
xrpllabsofficial/xrpld:latest \
create_keys
#ターミナルメッセージ
Validator keys stored in /root/.ripple/validator-keys.json
This file should be stored securely and not shared.
# validator-3のバリデータ鍵ペアを生成するコマンド
docker run --rm \
-v "$PWD/validator-3":/root/.ripple \
--entrypoint /opt/ripple/bin/validator-keys \
xrpllabsofficial/xrpld:latest \
create_keys
#ターミナルメッセージ
Validator keys stored in /root/.ripple/validator-keys.json
This file should be stored securely and not shared.
ディレクトリ構成
xrpl-private-network
├── validator-1
│ └── validator-keys.json
├── validator-2
│ └── validator-keys.json
└── validator-3
└── validator-keys.json
バリデータキーペアの例
{
"key_type" : "*******",
"public_key" : "****************************************************",
"revoked" : false,
"secret_key" : "*****************************************************",
"token_sequence" : *
}
バリデータトークンの作成
各ノードのバリデータキーペア(公開鍵・秘密鍵)もとにバリデータトークンを生成します。
バリデータトークン(validator_token)は、プライベートネットワーク内で各バリデータノードを認証し、不正なノードの参加を防ぐために使います。
ノード自己証明(Proof of Identity)
- 各バリデータノードは「自分が本当にその公開鍵を持つ正当なバリデータです」ということを示すために、あらかじめ生成したシークレット文字列(トークン)を保持します。
rippled.cfgの[validator_token]セクションにこのトークンを記載することで、起動時にリップルサーバー(rippled)が自分の公開鍵と紐づけて「このノードは正当な参加者です」と宣言できます。
ピア接続の許可制御
- ネットワークを構成する各ノードは、お互いのトークンを知らないと接続(Peer)を確立できない設定にできます。
- これにより、プライベートネットワーク外の第三者がポートをスキャンしてきても、正しいトークンを持たなければ相互通信できず、ネットワークへの不正侵入が防がれます。
合意形成(コンセンサス)への参加条件
- コンセンサス・プロトコルでは、ノードが提案(Proposal)を送信したり、投票したりする際に「正当なバリデータかどうか」を検証します。
- トークンを持つノードだけが「提案者リスト(Validator List)」に登録され、合意形成プロセスに参加できます。
バリデータトークン生成コマンドを実行
docker run --rm \
-v "$PWD/validator-1":/root/.ripple \
--entrypoint /opt/ripple/bin/validator-keys \
xrpllabsofficial/xrpld:latest \
create_token \
> validator-1/token.txt
docker run --rm \
-v "$PWD/validator-2":/root/.ripple \
--entrypoint /opt/ripple/bin/validator-keys \
xrpllabsofficial/xrpld:latest \
create_token \
> validator-2/token.txt
docker run --rm \
-v "$PWD/validator-3":/root/.ripple \
--entrypoint /opt/ripple/bin/validator-keys \
xrpllabsofficial/xrpld:latest \
create_token \
> validator-3/token.txt
ファイル ディレクトリ構成
├── validator-1
│ ├── token.txt
│ └── validator-keys.json
├── validator-2
│ ├── token.txt
│ └── validator-keys.json
└── validator-3
├── token.txt
└── validator-keys.json
ノードのディレクトリを作成
プライベートネットワーク内のすべてのノードのディレクトリにそれぞれの設定フォルダを作成します。
mkdir validator-1/config
mkdir validator-2/config
mkdir validator-3/config
ファイル ディレクトリ構成
xrpl-private-network
├── validator-1
│ ├── config
│ ├── token.txt
│ └── validator-keys.json
├── validator-2
│ ├── config
│ ├── token.txt
│ └── validator-keys.json
└── validator-3
├── config
├── token.txt
└── validator-keys.json
バリデータ設定ファイルの作成
バリデータのconfigディレクトリにrippled.cfgファイルを作成します。
以下のrippled.cfgテンプレートの情報を元に、validator-1、validator-2、validator-3ごとの固有のデーターを設定します。
[server]
port_rpc_admin_local
port_rpc
port_ws_admin_local
port_ws_public
port_peer
# ssl_key = /etc/ssl/private/server.key
# ssl_cert = /etc/ssl/certs/server.crt
[port_rpc_admin_local]
port = 5005
ip = 127.0.0.1
admin = 127.0.0.1
protocol = http
[port_ws_admin_local]
port = 6006
ip = 127.0.0.1
admin = 127.0.0.1
protocol = ws
[port_ws_public]
port = 80
ip = 0.0.0.0
protocol = ws
[port_peer]
port = 5123*
ip = 0.0.0.0
protocol = peer
[port_rpc]
port = 51234
ip = 0.0.0.0
admin = 127.0.0.1
protocol = https, http
[node_size]
small
# tiny
# small
# medium
# large
# huge
[node_db]
type=NuDB
path=/var/lib/rippled/db/nudb
advisory_delete=0
# How many ledgers do we want to keep (history)?
# Integer value that defines the number of ledgers
# between online deletion events
online_delete=256
[ledger_history]
# How many ledgers do we want to keep (history)?
# Integer value (ledger count)
# or (if you have lots of TB SSD storage): 'full'
256
[database_path]
/var/lib/rippled/db
[debug_logfile]
/var/log/rippled/debug.log
[sntp_servers]
time.windows.com
time.apple.com
time.nist.gov
pool.ntp.org
[ips_fixed]
validator_1 51235
validator_2 51236
validator_3 51237
[validators_file]
validators.txt
[rpc_startup]
{ "command": "log_level", "severity": "warning" }
# severity (order: lots of information .. only errors)
# debug
# info
# warn
# error
# fatal
[ssl_verify]
0
[validator_token]
<Add your validator token here>
[server] — ネットワーク I/O ポート
| 項目 | 説明 |
|---|---|
port_peer | 他ノードと合意形成メッセージをやりとりするポート (validator_1、validator_2、validator_3固有のポート番号を設定する) |
port_rpc_admin_local | 管理者用RPC(HTTP)をローカル限定で受け付ける |
port_ws_admin_local | 管理者用WebSocketをローカル限定で受け付ける |
[validator_token] — ノード認証トークン
<Add your validator token here>の箇所にvalidator_1、validator_2、validator_3/token.txt の内容(例:sXXXXXXXXXXXXXXXXXXXXXXXXXXXX)をそのまま貼り付けます。
[validators_file] と validators.txt — 信頼するバリデータ一覧
validator.txtファイルは、どのバリデータがネットワークから信頼されるかを定義します。
全ノード共通で公開キー一覧を設定します。
(validator-1、validator-2、validator-3のvalidator-keys.jsonファイルから公開鍵をコピーします。)
[validators]
nPUBKEY_OF_VALIDATOR1
nPUBKEY_OF_VALIDATOR2
nPUBKEY_OF_VALIDATOR3
db/ ディレクトリの作成
ホスト側に、各ノードがレジャー(台帳)データやトランザクション履歴を書き込む db/ ディレクトリを事前に作成する。
mkdir -p validator-1/db validator-2/db validator-3/db
ネットワークの開始
docker-compose.yml の作成
version: '3.9'
services:
validator_1:
container_name: validator_1
image: xrpllabsofficial/xrpld:latest
volumes:
- ./validator-1/config:/config # rippled.cfg, validators.txt, token.txt など
- ./validator-1/db:/config/db # ブロックチェーンデータの永続化
ports:
- "5005:5005" # RPC 管理用ポート
- "6006:6006" # WebSocket 管理用ポート
- "51235:51235" # Peer通信用ポート
validator_2:
container_name: validator_2
image: xrpllabsofficial/xrpld:latest
volumes:
- ./validator-2/config:/config
- ./validator-2/db:/config/db
ports:
- "5006:5005"
- "6007:6006"
- "51236:51236"
validator_3:
container_name: validator_3
image: xrpllabsofficial/xrpld:latest
volumes:
- ./validator-3/config:/config
- ./validator-3/db:/config/db
ports:
- "5007:5005"
- "6008:6006"
- "51237:51237"
ファイル ディレクトリ構成
xrpl-private-network
├── docker-compose.yml
├── validator-1
│ ├── config
│ │ ├── rippled.cfg
│ │ └── validators.txt
│ ├── db
│ ├── token.txt
│ └── validator-keys.json
├── validator-2
│ ├── config
│ │ ├── rippled.cfg
│ │ └── validators.txt
│ ├── db
│ ├── token.txt
│ └── validator-keys.json
└── validator-3
├── config
│ ├── rippled.cfg
│ └── validators.txt
├── db
├── token.txt
└── validator-keys.json
ネットワークを起動
docker-compose up -d
#ターミナルメッセージ
docker compose up -d
WARN[0000] /home/omo-y/container/xrpl-private-network/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion
[+] Running 4/4
✔ Network xrpl-private-network_default Created 0.0s
✔ Container validator_3 Started 0.5s
✔ Container validator_2 Started 0.5s
✔ Container validator_1 Started 0.4s
omo-y@DESKTOP-IHHI957:~/container/xrpl-private-network$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8a488ed7c8f2 xrpllabsofficial/xrpld:latest "/entrypoint.sh" 10 seconds ago Up 9 seconds 80/tcp, 443/tcp, 51235/tcp, 0.0.0.0:51237->51237/tcp, 0.0.0.0:5007->5005/tcp, 0.0.0.0:6008->6006/tcp validator_3
b7fe03a4e01a xrpllabsofficial/xrpld:latest "/entrypoint.sh" 10 seconds ago Up 9 seconds 80/tcp, 443/tcp, 51235/tcp, 0.0.0.0:51236->51236/tcp, 0.0.0.0:5006->5005/tcp, 0.0.0.0:6007->6006/tcp validator_2
82cfeee81d2f xrpllabsofficial/xrpld:latest "/entrypoint.sh" 10 seconds ago Up 9 seconds 80/tcp, 0.0.0.0:5005->5005/tcp, 0.0.0.0:6006->6006/tcp, 443/tcp, 0.0.0.0:51235->51235/tcp validator_1
ネットワークを検証
サーバー状態の確認
docker exec -it validator_1 /bin/bash #コンテナのシェルに入る
# rippled server_info | grep server_state
#ターミナルメッセージ
Loading: "/etc/opt/ripple/rippled.cfg"
2025-May-20 07:56:54.418106415 UTC HTTPClient:NFO Connecting to 127.0.0.1:5005
"server_state" : "proposing",
"server_state_duration_us" : "139104238",
バリデータに接続しているピア数の確認
# rippled server_info | grep peers
#ターミナルメッセージ
Loading: "/etc/opt/ripple/rippled.cfg"
2025-May-20 07:57:26.021801137 UTC HTTPClient:NFO Connecting to 127.0.0.1:5005
"peers" : 2,
genesisのアカウント情報の確認
rippled account_info rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh validated strict
#ターミナルメッセージ
Loading: "/etc/opt/ripple/rippled.cfg"
2025-May-20 08:15:39.354073416 UTC HTTPClient:NFO Connecting to 127.0.0.1:5005
{
"result" : {
"account_data" : {
"Account" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Balance" : "100000000000000000",
"Flags" : 0,
"LedgerEntryType" : "AccountRoot",
"OwnerCount" : 0,
"PreviousTxnID" : "0000000000000000000000000000000000000000000000000000000000000000",
"PreviousTxnLgrSeq" : 0,
"Sequence" : 1,
"index" : "2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8"
},
"account_flags" : {
"defaultRipple" : false,
"depositAuth" : false,
"disableMasterKey" : false,
"disallowIncomingXRP" : false,
"globalFreeze" : false,
"noFreeze" : false,
"passwordSpent" : false,
"requireAuthorization" : false,
"requireDestinationTag" : false
},
"ledger_current_index" : 400,
"status" : "success",
"validated" : false
}
}
ジェネシスアカウントのアドレス(下記)は、rippled の「スタンドアロンモードで新規ジェネシスレジャーを作成」機能で使われるデフォルトのジェネシスレジャーにハードコードされたアカウントです。
rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh
テストトランザクションの実行
XRP Ledger(XRPL)はビットコインのようなProof-of-Workマイニングを採用しておらず、全XRP(総発行量1000億XRP)はローンチ時に一括発行済みです。
XRPLは約3~5秒ごとに「Unique Node List(UNL)」に登録された独立したバリデータノード同士で合意(コンセンサス)を行い、次のレジャー(台帳)を確定します。
バリデータは取引時に発生する手数料(drops)を受け取れます。
トランザクションの送信
サンプルの宛先アカウント(rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh)にトランザクションを送信する。
validator_1コンテナに入り、1000000000 XRPを手数料10XRPで送金するためにrippled submitメソッドを実行する。
validator_1コンテナに入る
$docker exec -it validator_1 /bin/bash
コンテナ内でトランザクションを送信する。
# rippled submit 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb' '{ "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "Amount": "1000000000", "Destination": "r9wRwVgL2vWVnKhTPdtxva5vdH7FNw1zPs", "TransactionType": "Payment", "Fee": "10" }'
Loading: "/etc/opt/ripple/rippled.cfg"
2025-May-20 18:14:39.686240919 UTC HTTPClient:NFO Connecting to 127.0.0.1:5005
{
"result" : {
"deprecated" : "Signing support in the 'submit' command has been deprecated and will be removed in a future version of the server. Please migrate to a standalone signing tool.",
"engine_result" : "tesSUCCESS",
"engine_result_code" : 0,
"engine_result_message" : "The transaction was applied. Only final in a validated ledger.",
"status" : "success",
"tx_blob" : "1200002280000000240000000161400000003B9ACA0068400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074463044022057CCEED351A4278F35C13FD104A55338DC8F48C1F9902D58045A4CD0CE89C92A0220184026BD3B1E2C21239017CAF1BBF68335EDC57F6F98D952E263763DE449561B8114B5F762798A53D543A014CAF8B297CFF8F2F937E883145988EBB744055F4E8BDC7F67FD53EB9FCF961DC0",
"tx_json" : {
"Account" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Amount" : "1000000000",
"DeliverMax" : "1000000000",
"Destination" : "r9wRwVgL2vWVnKhTPdtxva5vdH7FNw1zPs",
"Fee" : "10",
"Flags" : 2147483648,
"Sequence" : 1,
"SigningPubKey" : "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
"TransactionType" : "Payment",
"TxnSignature" : "3044022057CCEED351A4278F35C13FD104A55338DC8F48C1F9902D58045A4CD0CE89C92A0220184026BD3B1E2C21239017CAF1BBF68335EDC57F6F98D952E263763DE449561B",
"hash" : "EB516738841794B24819C68273E0F853A3D234350E6534F7F2841F620CE99437"
}
}
}
宛先アカウント(r9wRwVgL2vWVnKhTPdtxva5vdH7FNw1zPs) に 1000000000 XRP があることを確認する。
validator_1、validator_2、validator_3で同じ残高1000000000XRPを持つことを確認する。
# rippled account_info r9wRwVgL2vWVnKhTPdtxva5vdH7FNw1zPs validated strict
Loading: "/etc/opt/ripple/rippled.cfg"
2025-May-20 18:28:45.697686627 UTC HTTPClient:NFO Connecting to 127.0.0.1:5005
{
"result" : {
"account_data" : {
"Account" : "r9wRwVgL2vWVnKhTPdtxva5vdH7FNw1zPs",
"Balance" : "1000000000",
"Flags" : 0,
"LedgerEntryType" : "AccountRoot",
"OwnerCount" : 0,
"PreviousTxnID" : "EB516738841794B24819C68273E0F853A3D234350E6534F7F2841F620CE99437",
"PreviousTxnLgrSeq" : 54,
"Sequence" : 1,
"index" : "0F2E4615AE24EEF58EE82BD1E67D237234ED41BFC8B7885630B7AC05082E97AA"
},
"account_flags" : {
"defaultRipple" : false,
"depositAuth" : false,
"disableMasterKey" : false,
"disallowIncomingXRP" : false,
"globalFreeze" : false,
"noFreeze" : false,
"passwordSpent" : false,
"requireAuthorization" : false,
"requireDestinationTag" : false
},
"ledger_current_index" : 333,
"status" : "success",
"validated" : false
}
}

