概要
マニュアルビルドしたカタパルトサーバーを使ってプライベートネットワークを立ち上げます。
※この記事はメモ書き程度の精度しかないので、後日再度検証してまとめます。
基本的には以下の公式に従ってやればOKなのですが、非常に設定が複雑です。
公式の手順は複雑すぎて大変なのでここでは楽をしてsymbol-networkツールを使います。
以下よりgit clone するので、適当なディレクトリで作業してください。
symbol-networkを取得
$ git clone https://github.com/fboucquez/symbol-network.git
$ cd symbol-network
NPMからでもsymbol-networkはダウンロードできますが、NPMのものは内部で参照しているsymbol-bootstrapのバージョンが古いのでここではGithubからCloneしてローカルインストールをします。
symbol-bootstrapのバージョンを上げる
symbol-networkのpackage.json
のsymbol-bootstrapのバージョンを1.1.4
から1.1.10
に変更します。
ついでにわかりやすいようにバージョンも変更しておきます。
sdkのバージョンも上げておきたいところですが、今のところどこに影響が出るのかわからないので今回はそのままにしておきます。
{
"name": "symbol-network",
- "version": "0.0.2",
+ "version": "0.0.3",
"description": "CLI tools to create node clusters for new or existing Symbol networks.",
"bin": {
"symbol-network": "bin/run"
},
"homepage": "https://github.com/fboucquez/symbol-network",
"bugs": "https://github.com/fboucquez/symbol-network/issues",
"scripts": {
"doc": "shx mkdir -p ts-docs && typedoc --out \"ts-docs\" src && touch ./ts-docs/.nojekyll",
"clean": "npx shx rm -rf ./lib",
"purge": "npx shx rm -rf lib coverage node_modules target .nyc_output logs.log ts-docs",
"lint": "eslint --cache src/ test/ --ext .ts",
"lint:fix": "eslint src/ test/ --ext .ts --fix",
"prettier": "prettier --write ./src",
"style:fix": "npm run create-index-files && npm run prettier && npm run lint:fix && npm run oclif-doc",
"create-index-files": "cti create ./src -b -n -e commands",
"postpack": "npx shx rm -f oclif.manifest.json",
"posttest": "eslint src/ test/ --ext .ts",
"oclif-doc": "oclif-dev manifest && oclif-dev readme --multi",
"watch": "tsc --watch",
"compile": "tsc ",
"build": "npx shx rm -rf lib && npm run compile",
"prepack": "npx shx rm -rf lib && npm run compile && npm run oclif-doc",
"test": "nyc --reporter=lcov --extension .ts mocha -r ts-node/register --timeout 900000 --forbid-only \"test/**/*.test.ts\"",
"e2e": "nyc --reporter=lcov --extension .ts mocha -r ts-node/register --timeout 900000 --forbid-only \"test/**/*.e2e.ts\"",
"coveralls-report": "cat ./coverage/lcov.info | coveralls",
"version": "echo $npm_package_version",
"install-cli": "npm pack && npm i -g"
},
"engines": {
"node": ">=12.0.0"
},
"files": [
"/bin",
"/lib",
"/npm-shrinkwrap.json",
"/oclif.manifest.json"
],
"oclif": {
"commands": "./lib/commands",
"bin": "symbol-network",
"plugins": [
"@oclif/plugin-autocomplete",
"@oclif/plugin-help"
]
},
"keywords": [],
"author": "Fernando Boucquez <fboucquez@gmail.com>",
"license": "Apache-2.0",
"mocha": {
"timeout": 40000
},
"types": "lib/index.d.ts",
"dependencies": {
"@oclif/command": "^1.8.16",
"@oclif/config": "^1.18.3",
"@oclif/plugin-autocomplete": "^1.2.0",
"@oclif/plugin-help": "^5.1.11",
"cross-fetch": "^3.1.5",
"figlet": "^1.5.2",
"inquirer": "^8.2.0",
"lodash": "^4.17.21",
"remove": "^0.1.5",
"rxjs": "^7.5.2",
- "symbol-bootstrap": "^1.1.4",
+ "symbol-bootstrap": "^1.1.10",
"symbol-sdk": "^1.0.4-alpha-202112211435",
"tslib": "^2.3.1",
"winston": "^3.5.1"
},
"devDependencies": {
"@oclif/dev-cli": "^1.26.10",
"@oclif/test": "^2.0.3",
"@types/chai": "^4.3.0",
"@types/figlet": "^1.5.4",
"@types/inquirer": "^8.2.0",
"@types/lodash": "^4.14.178",
"@types/mocha": "^9.1.0",
"@types/node": "^17.0.14",
"@types/semver": "^7.3.9",
"@types/winston": "^2.4.4",
"@typescript-eslint/eslint-plugin": "^5.10.2",
"@typescript-eslint/parser": "^5.10.2",
"chai": "^4.3.6",
"coveralls": "^3.1.1",
"create-ts-index": "^1.14.0",
"dir-compare": "^4.0.0",
"eslint": "^8.8.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"mocha": "^9.2.0",
"mocha-lcov-reporter": "^1.3.0",
"mock-stdin": "^1.0.0",
"nyc": "^15.1.0",
"prettier": "^2.5.1",
"prettier-plugin-organize-imports": "^2.3.4",
"shx": "^0.3.4",
"sinon": "^13.0.1",
"ts-node": "^10.4.0",
"typedoc": "^0.22.11",
"typescript": "^4.5.5"
}
}
ローカルインストール
$ npm install -g .
$ symbol-network -v
>symbol-network/0.0.3 linux-x64 node-v18.19.0
バージョンが0.0.3 になっていればOKです。
ネメシス用の設定ファイルの生成
先ほどカタパルトサーバーをビルドしたディレクトに移動して作業を行います。
cd catapult-client/_build
init
コマンドを実行すると色々と聞かれるので、色々と聞かれるのでご自分の設定を作成してください。(長いので説明は割愛します)
試すだけならひたすらEnterでOKです。最後にDo you want to create more nodes?
と聞かれるのでn
をするとツールが終了します。
$ symbol-network init
_ _ _ _
___ _ _ _ __ ___ | |__ ___ | | _ __ ___ | |_ __ __ ___ _ __ | | __
/ __|| | | || '_ ` _ \ | '_ \ / _ \ | | _____ | '_ \ / _ \| __|\ \ /\ / // _ \ | '__|| |/ /
\__ \| |_| || | | | | || |_) || (_) || ||_____|| | | || __/| |_ \ V V /| (_) || | | <
|___/ \__, ||_| |_| |_||_.__/ \___/ |_| |_| |_| \___| \__| \_/\_/ \___/ |_| |_|\_\
|___/
2023-12-29T16:10:49.446Z info
2023-12-29T16:10:49.447Z info Welcome to the symbol-network tool.
2023-12-29T16:10:49.447Z info
2023-12-29T16:10:49.447Z info This tool will allow you creating a new network or a node cluster for an existing network.
2023-12-29T16:10:49.447Z info
2023-12-29T16:10:49.447Z info First you need to decide if you are creating a new network or creating nodes to join an existing network.
2023-12-29T16:10:49.447Z info
? Are you creating a new network? Yes
2023-12-29T16:15:21.306Z info
2023-12-29T16:15:21.306Z info The new network will be based on an existing network. You can select an out-of-the box preset from Symbol Bootstrap or you can provide a custom network preset to be based one
2023-12-29T16:15:21.306Z info
? Select the Bootstrap profile to base your new network from: Bootstrap Preset
? Enter the domain to be used to be used in your nodes mycompany.com
? Is the Domain mycompany.com correct? Yes
? Enter a suffix for node generated domain names and urls myc
? Is the Suffix myc correct? Yes
? Enter the pattern used to generate hostnames and friendly names $suffix-$nickname-$friendlyNumber
? Is the friendlyNamePattern $suffix-$nickname-$friendlyNumber correct? Yes
? Enter the password used to encrypt and decrypt the local key store (MASTER PASSWORD).
2023-12-29T16:15:36.628Z warn Password has not been provided (empty text)! It's recommended to use one for security!
? What's the network type you want to create? Testnet
? Enter a name for the network. My Company Testnet Network
? Is the Network Name My Company Testnet Network correct? Yes
? Enter the generation hash seed to identify the network 5F45C8F5CEA32ACC7385BBC3E4FBADF1B5812AED095118567BD12099C7BF7650
? Is the Generation Hash Seed 5F45C8F5CEA32ACC7385BBC3E4FBADF1B5812AED095118567BD12099C7BF7650 correct? Yes
? Enter the epoch adjustment value to offset deadlines. 1703866541
? Is the Epoch Adjustment 1703866541 correct? Yes
? Enter the basename for the network aliases cat
? Is the Network basename Alias cat correct? Yes
? Enter the alias for the Network Currency currency
? Is the Network Currency Name currency correct? Yes
? Enter the alias for the Harvest Currency harvest
? Is the Harvest Currency Name harvest correct? Yes
? Enter the 64 HEX private key Nemesis Signer Account (or press enter to accept the auto generated): ****************************************************************
? Is the Nemesis Signer Account address TCYJT6IFZ5SULPFPL4HCH2K4EHXQTGJI42YQXGY public key 2474619FF9AFAFCE511686541E359409E739BA6F465F1246EBEAB67620360853 correct? Yes
? Enter the 64 HEX private key Founder Account (or press enter to accept the auto generated): ****************************************************************
? Is the Founder Account address TAHVAZ75UCVK6RE5FD4AZPSGXCLAPBYSULR7JJY public key 1A89A1791EF686E97AAA4F16B17BCC889A8C07A90FA356DEBE6ED7532DD94AC8 correct? Yes
? Do you want to have a Faucet account? Yes
? Enter the 64 HEX private key Faucet Account (or press enter to accept the auto generated): ****************************************************************
? Is the Faucet Account address TCG7EXSVKZAI3O534KXPSLOPY7BZM624JIPC2MQ public key 33791E4C1B63AA364F1EFD32674A906CE9BD28C529DAAC4269F77D46521B7667 correct? Yes
? What's the initial currency coin balance for the Faucet Account TCG7EXSVKZAI3O534KXPSLOPY7BZM624JIPC2MQ? 449949995
? Is the Balance 449949995 correct? Yes
? What's the initial harvest coin balance for the Faucet Account TCG7EXSVKZAI3O534KXPSLOPY7BZM624JIPC2MQ? 750
? Is the Balance 750 correct? Yes
2023-12-29T16:16:28.963Z info
2023-12-29T16:16:28.964Z info In addition to the node, faucet and founder accounts, you can include (opt-in) more accounts into the nemesis block by distributing currency coins.
? Do you want to distribute coin currency to different accounts on the nemesis block? No
2023-12-29T16:16:30.516Z info
2023-12-29T16:16:30.517Z info In addition to the node, faucet and founder accounts, you can include (opt-in) more accounts into the nemesis block by distributing harvest coins.
? Do you want to distribute coin harvest to different accounts on the nemesis block? No
? Enter the 64 HEX private key Harvest Network Fee Sink Account (or press enter to accept the auto generated): ****************************************************************
? Is the Harvest Network Fee Sink Account address TAZIMZPHTUGQTV2NSYKCQP3W5PFHXO756CEUYUI public key CED044F7EB9D1A7E0CD2DFA8D2A74B3E0B67D73072020369B61580B0FE56E31E correct? Yes
? Enter the 64 HEX private key Namespace Rental Fee Sink Account (or press enter to accept the auto generated): ****************************************************************
? Is the Namespace Rental Fee Sink Account address TAOLJZG6GH3FFAJ25BCCMY6IK7MAMUNLXOVSNNA public key 40AD377CC34C08209F1EE05287789FD12414D1962821B544F61243BC8F965DAD correct? Yes
? Enter the 64 HEX private key Mosaic Rental Fee Sink Account (or press enter to accept the auto generated): ****************************************************************
? Is the Mosaic Rental Fee Sink Account address TAXSMYMTSPVPOIGC5OUT35BNFRDHT6FR7TBKD7A public key 510A2A553527A01A8662BC982E81E3166F80A33A0049F4F9EFDFCB35674537D9 correct? Yes
2023-12-29T16:16:36.262Z info
2023-12-29T16:16:36.263Z info The initial network preset custom-network-preset.yml for the new network has been stored. This file will be updated in the following steps.
2023-12-29T16:16:36.263Z info
2023-12-29T16:16:36.263Z info
2023-12-29T16:16:36.263Z info
? Select the node type you want to create Voting Dual
? How many nodes of type Voting Dual do you want to create? 3
? What's the initial currency balance for the Voting Dual nodes? 3000000
? Is the Balance 3000000 correct? Yes
? What's the initial harvest balance for the Voting Dual nodes? 150
? Is the Balance 150 correct? Yes
? The nick name of the these nodes dual
? Is the Nodes's Nick Name dual correct? Yes
? Select the HTTP protocol for your Rest Gateways HttpAndHttps
? Do you want to create 3 nodes of type Voting Dual each with balance of 3000000, 150? Yes
? Do you want to create more nodes? No
2023-12-29T16:17:39.076Z info
2023-12-29T16:17:39.076Z info You have created the initial network-input.yml. Have a look and once once you are happy, run:
2023-12-29T16:17:39.076Z info
2023-12-29T16:17:39.076Z info $ symbol-network expandNodes
2023-12-29T16:17:39.077Z info
全ての問いに答えるとcustom-network-preset.yml
key-store.yml
network-input.yml
が作成されていると思います。
以下は適当にEnterを押して作ったcustom-network-preset.yml
ファイルです。
networkDescription: My Company Testnet Network
initialCurrencyAtomicUnits: 8998999998000000
maxMosaicAtomicUnits: 9000000000000000
totalChainImportance: 15000000
minHarvesterBalance: 500
maxHarvesterBalance: 50000000000000
networkType: 152
minVoterBalance: 50000
baseNamespace: cat
explorerUrl: http://localhost:90/
faucetUrl: http://localhost:100/
beneficiaryAddress: ''
votingKeyDesiredLifetime: 720
votingKeyDesiredFutureLifetime: 120
lastKnownNetworkEpoch: 1
restExtensions: accountLink, aggregate, lockHash, lockSecret, mosaic, metadata, multisig, namespace, receipts, restrictions, transfer
nemesis:
mosaics:
-
name: currency
divisibility: 6
duration: 0
supply: 8998999998000000
isTransferable: true
isSupplyMutable: false
isRestrictable: false
accounts: 5
-
name: harvest
divisibility: 3
duration: 0
supply: 15000000
isTransferable: true
isSupplyMutable: true
isRestrictable: false
accounts: 2
inflation:
starting-at-height-1: 0
starting-at-height-10000: 0
nemesisSeedFolder: nemesis-seed
nemesisSignerPublicKey: 2474619FF9AFAFCE511686541E359409E739BA6F465F1246EBEAB67620360853
harvestNetworkFeeSinkAddress: TAZIMZPHTUGQTV2NSYKCQP3W5PFHXO756CEUYUI
namespaceRentalFeeSinkAddress: TAOLJZG6GH3FFAJ25BCCMY6IK7MAMUNLXOVSNNA
mosaicRentalFeeSinkAddress: TAXSMYMTSPVPOIGC5OUT35BNFRDHT6FR7TBKD7A
nemesisGenerationHashSeed: 5F45C8F5CEA32ACC7385BBC3E4FBADF1B5812AED095118567BD12099C7BF7650
epochAdjustment: 1703866541s
このファイルは今回、特に変更する必要はありませんが、諸々の追加設定を行うファイルになります。
続けて、以下のコマンドを実行します。
$ symbol-network expandNodes
network.yml
が生成されます。
preset: custom-network-preset.yml
cloneFromPreset: bootstrap
domain: mycompany.com
suffix: myc
friendlyNamePattern: $suffix-$nickname-$friendlyNumber
networkType: 152
isNewNetwork: true
faucetBalances:
- 449949995
- 750
additionalCurrencyDistributions:
- []
- []
customNetworkPreset:
nemesis:
mosaics:
-
name: currency
-
name: harvest
networkDescription: My Company Testnet Network
nemesisGenerationHashSeed: 5F45C8F5CEA32ACC7385BBC3E4FBADF1B5812AED095118567BD12099C7BF7650
epochAdjustment: 1703866541s
baseNamespace: cat
nodes:
-
number: 1
friendlyName: myc-dual-001
assembly: dual
hostname: myc-dual-001.mycompany.com
customPreset:
privateKeySecurityMode: PROMPT_MAIN_TRANSPORT
nodes:
-
friendlyName: myc-dual-001
host: myc-dual-001.mycompany.com
voting: true
harvesting: true
dockerComposeDebugMode: false
brokerDockerComposeDebugMode: false
gateways:
-
openPort: true
httpsProxies:
-
excludeDockerService: false
nickName: dual
nodeType: VotingDual
balances:
- 3000000
- 150
restProtocol: HttpAndHttps
-
number: 2
friendlyName: myc-dual-002
assembly: dual
hostname: myc-dual-002.mycompany.com
customPreset:
privateKeySecurityMode: PROMPT_MAIN_TRANSPORT
nodes:
-
friendlyName: myc-dual-002
host: myc-dual-002.mycompany.com
voting: true
harvesting: true
dockerComposeDebugMode: false
brokerDockerComposeDebugMode: false
gateways:
-
openPort: true
httpsProxies:
-
excludeDockerService: false
nickName: dual
nodeType: VotingDual
balances:
- 3000000
- 150
restProtocol: HttpAndHttps
-
number: 3
friendlyName: myc-dual-003
assembly: dual
hostname: myc-dual-003.mycompany.com
customPreset:
privateKeySecurityMode: PROMPT_MAIN_TRANSPORT
nodes:
-
friendlyName: myc-dual-003
host: myc-dual-003.mycompany.com
voting: true
harvesting: true
dockerComposeDebugMode: false
brokerDockerComposeDebugMode: false
gateways:
-
openPort: true
httpsProxies:
-
excludeDockerService: false
nickName: dual
nodeType: VotingDual
balances:
- 3000000
- 150
restProtocol: HttpAndHttps
最後に以下のコマンドを実行してネメシスファイルを生成します。
$ symbol-network generateNemesis
実行すると、nemesis-seed
nemesis-target
という2フォルダが生成されていると思います。
今回必要になるのは、nemesis-target/nemesis
フォルダとnemesis-target/nodes/node/server-config/resources
フォルダとnemesis-target/nodes/node/cert
フォルダです。
上記の3つのフォルダをカレントディレクトにコピーします。
また、
$ cp -r nemesis-target/nemesis .
$ cp -r nemesis-target/nodes/node/server-config/resources .
$ cp -r nemesis-target/nodes/node/cert .
# $ cp nemesis/server-config/block-properties-file.properties resources/testnet.properties
ディレクトリの修正
resources/config-user.properties
を以下のように修正します。
[account]
enableDelegatedHarvestersAutoDetection = true
[storage]
- seedDirectory = ./seed
+ seedDirectory = ../nemesis/seed
- certificateDirectory = ./cert
+ certificateDirectory = ../cert
- dataDirectory = ./data
+ dataDirectory = ../data
- pluginsDirectory = /usr/catapult/lib
+ pluginsDirectory = .
votingKeysDirectory = ./votingkeys
ノードの実行
それでは、ノードの起動準備ができたので実際にノードを起動してみます。
まずは、データの保存される領域を作成します。
$ mkdir data
カタパルトサーバーを実行します。
$ cd bin
$ ./catapult.server
適当にノードを作ったせいで色々とエラーになっていますが、ブロックは進んでいるようです。
(ノードを3台で作成したので接続しにいっているがそもそも1台でしか実行してないのでエラーになっている)
mongodbのインストール
続けてmongodbの設定を行います。
ノードはControl+Cで停止しておいてください。
ノードが停止したら以下の手順でmongodbをインストールします。
# GPG公開鍵の追加
$ curl -fsSL https://www.mongodb.org/static/pgp/server-5.0.asc | sudo apt-key add -
# リポジトリの追加
$ echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/5.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-5.0.list
# インストール
$ sudo apt update
$ sudo apt install mongodb-org
# 自動起動の設定
$ sudo systemctl enable mongod
# サービス起動
$ sudo systemctl start mongod.service
データベースの実行
$ mongod --dbpath=dbfiles --wiredTigerCacheSizeGB 2 --bind_ip 127.0.0.1
{"t":{"$date":"2023-12-30T21:08:14.811+09:00"},"s":"I", "c":"NETWORK", "id":4915701, "ctx":"-","msg":"Initialized wire specification","attr":{"spec":{"incomingExternalClient":{"minWireVersion":0,"maxWireVersion":13},"incomingInternalClient":{"minWireVersion":0,"maxWireVersion":13},"outgoing":{"minWireVersion":0,"maxWireVersion":13},"isInternalClient":true}}}
{"t":{"$date":"2023-12-30T21:08:14.812+09:00"},"s":"I", "c":"CONTROL", "id":23285, "ctx":"-","msg":"Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none'"}
{"t":{"$date":"2023-12-30T21:08:14.813+09:00"},"s":"W", "c":"ASIO", "id":22601, "ctx":"main","msg":"No TransportLayer configured during NetworkInterface startup"}
{"t":{"$date":"2023-12-30T21:08:14.813+09:00"},"s":"I", "c":"NETWORK", "id":4648601, "ctx":"main","msg":"Implicit TCP FastOpen unavailable. If TCP FastOpen is required, set tcpFastOpenServer, tcpFastOpenClient, and tcpFastOpenQueueSize."}
{"t":{"$date":"2023-12-30T21:08:14.815+09:00"},"s":"W", "c":"ASIO", "id":22601, "ctx":"main","msg":"No TransportLayer configured during NetworkInterface startup"}
{"t":{"$date":"2023-12-30T21:08:14.815+09:00"},"s":"I", "c":"REPL", "id":5123008, "ctx":"main","msg":"Successfully registered PrimaryOnlyService","attr":{"service":"TenantMigrationDonorService","ns":"config.tenantMigrationDonors"}}
{"t":{"$date":"2023-12-30T21:08:14.815+09:00"},"s":"I", "c":"REPL", "id":5123008, "ctx":"main","msg":"Successfully registered PrimaryOnlyService","attr":{"service":"TenantMigrationRecipientService","ns":"config.tenantMigrationRecipients"}}
{"t":{"$date":"2023-12-30T21:08:14.815+09:00"},"s":"I", "c":"CONTROL", "id":5945603, "ctx":"main","msg":"Multi threading initialized"}
{"t":{"$date":"2023-12-30T21:08:14.815+09:00"},"s":"I", "c":"CONTROL", "id":4615611, "ctx":"initandlisten","msg":"MongoDB starting","attr":{"pid":552099,"port":27017,"dbPath":"dbfiles","architecture":"64-bit","host":"vmi649314.contaboserver.net"}}
{"t":{"$date":"2023-12-30T21:08:14.815+09:00"},"s":"I", "c":"CONTROL", "id":23403, "ctx":"initandlisten","msg":"Build Info","attr":{"buildInfo":{"version":"5.0.23","gitVersion":"3367195a14d0ba2734d2ba2719294fb974ad0834","openSSLVersion":"OpenSSL 1.1.1f 31 Mar 2020","modules":[],"allocator":"tcmalloc","environment":{"distmod":"ubuntu2004","distarch":"x86_64","target_arch":"x86_64"}}}}
{"t":{"$date":"2023-12-30T21:08:14.815+09:00"},"s":"I", "c":"CONTROL", "id":51765, "ctx":"initandlisten","msg":"Operating System","attr":{"os":{"name":"Ubuntu","version":"20.04"}}}
{"t":{"$date":"2023-12-30T21:08:14.815+09:00"},"s":"I", "c":"CONTROL", "id":21951, "ctx":"initandlisten","msg":"Options set by command line","attr":{"options":{"net":{"bindIp":"127.0.0.1"},"storage":{"dbPath":"dbfiles","wiredTiger":{"engineConfig":{"cacheSizeGB":2}}}}}}
{"t":{"$date":"2023-12-30T21:08:14.816+09:00"},"s":"E", "c":"NETWORK", "id":23024, "ctx":"initandlisten","msg":"Failed to unlink socket file","attr":{"path":"/tmp/mongodb-27017.sock","error":"Operation not permitted"}}
{"t":{"$date":"2023-12-30T21:08:14.816+09:00"},"s":"F", "c":"-", "id":23091, "ctx":"initandlisten","msg":"Fatal assertion","attr":{"msgid":40486,"file":"src/mongo/transport/transport_layer_asio.cpp","line":1131}}
{"t":{"$date":"2023-12-30T21:08:14.816+09:00"},"s":"F", "c":"-", "id":23092, "ctx":"initandlisten","msg":"\n\n***aborting after fassert() failure\n\n"}
インデックス構築
$ mongo 127.0.0.1/catapult < ../scripts/mongo/mongoDbPrepare.js
MongoDB shell version v5.0.23
connecting to: mongodb://127.0.0.1:27017/catapult?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("8cb73084-f487-4553-860d-392be66724b9") }
MongoDB server version: 5.0.23
================
Warning: the "mongo" shell has been superseded by "mongosh",
which delivers improved usability and compatibility.The "mongo" shell has been deprecated and will be removed in
an upcoming release.
For installation instructions, see
https://docs.mongodb.com/mongodb-shell/install/
================
Loading LockHash
{"t":{"$date":"2023-12-30T12:09:37.072Z"},"s":"E", "c":"-", "id":22779, "ctx":"js","msg":"file [{filename}] doesn't exist","attr":{"filename":"mongoLockHashDbPrepare.js"}}
Error: error loading js file: mongoLockHashDbPrepare.js :
@(shell):7:3
preparePluginDbCollections@(shell):5:2
@(shell):1:11
===== accounts INDEXES =====
{ "_id" : 1 }
{ "account.publicKey" : 1 }
{ "account.address" : 1 }
===== addressResolutionStatements INDEXES =====
{ "_id" : 1 }
{ "statement.height" : 1, "statement.unresolved" : 1 }
===== blocks INDEXES =====
{ "_id" : 1 }
{ "block.signerPublicKey" : 1 }
{ "block.timestamp" : -1 }
{ "block.height" : -1 }
{ "block.type" : 1, "block.height" : -1 }
{ "block.signerPublicKey" : 1, "block.height" : -1 }
{ "block.beneficiaryAddress" : 1, "block.height" : -1 }
===== finalizedBlocks INDEXES =====
{ "_id" : 1 }
{ "block.finalizationEpoch" : -1 }
{ "block.height" : -1 }
{ "block.finalizationEpoch" : -1, "block.finalizationPoint" : -1 }
===== mosaicResolutionStatements INDEXES =====
{ "_id" : 1 }
{ "statement.height" : 1, "statement.unresolved" : 1 }
===== partialTransactions INDEXES =====
{ "_id" : 1 }
{ "transaction.signerPublicKey" : 1, "_id" : -1 }
{ "transaction.recipientAddress" : 1, "_id" : -1 }
{ "meta.hash" : 1 }
{ "meta.addresses" : 1 }
{ "meta.aggregateId" : 1 }
{ "meta.aggregateHash" : 1 }
===== system.profile INDEXES =====
===== transactionStatements INDEXES =====
{ "_id" : 1 }
{
"statement.height" : 1,
"statement.source.primaryId" : 1,
"statement.source.secondaryId" : 1
}
===== transactionStatuses INDEXES =====
{ "_id" : 1 }
{ "status.hash" : 1 }
{ "status.deadline" : -1 }
===== transactions INDEXES =====
{ "_id" : 1 }
{ "transaction.signerPublicKey" : 1, "_id" : -1 }
{ "transaction.recipientAddress" : 1, "_id" : -1 }
{ "meta.hash" : 1 }
{ "meta.addresses" : 1 }
{ "meta.aggregateId" : 1 }
{ "meta.height" : -1 }
{ "transaction.deadline" : -1 }
{ "transaction.cosignatures.signerPublicKey" : 1 }
{ "transaction.id" : 1, "transaction.type" : 1 }
===== unconfirmedTransactions INDEXES =====
{ "_id" : 1 }
{ "transaction.signerPublicKey" : 1, "_id" : -1 }
{ "transaction.recipientAddress" : 1, "_id" : -1 }
{ "meta.hash" : 1 }
{ "meta.addresses" : 1 }
{ "meta.aggregateId" : 1 }
{ "meta.aggregateHash" : 1 }
bye
ノードの実行
$ cd bin
$ ./catapult.server
設定ファイルの修正
(これは不要かもしれない)
resources/config-database.properties
ファイルを以下のように修正します
[database]
- databaseUri = mongodb://db:27017
+ databaseUri = mongodb://127.0.0.1:27017
databaseName = catapult
maxWriterThreads = 8
maxDropBatchSize = 10
writeTimeout = 10m
[plugins]
catapult.mongo.plugins.accountlink = true
catapult.mongo.plugins.aggregate = true
catapult.mongo.plugins.lockhash = true
catapult.mongo.plugins.locksecret = true
catapult.mongo.plugins.metadata = true
catapult.mongo.plugins.mosaic = true
catapult.mongo.plugins.multisig = true
catapult.mongo.plugins.namespace = true
catapult.mongo.plugins.restrictionaccount = true
catapult.mongo.plugins.restrictionmosaic = true
catapult.mongo.plugins.transfer = true
brokerの実行
別の端末を開いてbinフォルダ以下でコマンドを実行します
$ cd bin
$ ./catapult.broker ..
エラーが出る場合
Copyright (c) Jaguar0625, gimre, BloodyRookie, Tech Bureau, Corp.
catapult version: 1.0.3.6 afea1ae8 [v1.0.3.6]
loading resources from "../resources"
loading configuration from "../resources/config-inflation.properties"
loading configuration from "../resources/config-extensions-broker.properties"
loading configuration from "../resources/config-user.properties"
loading configuration from "../resources/config-logging-broker.properties"
loading configuration from "../resources/config-node.properties"
loading configuration from "../resources/config-network.properties"
2023-12-30 22:42:44.414491 0x00007fc297d2f2c0: <warning> (io::FileLock.cpp@75) LockOpen failed: 17
2023-12-30 22:42:44.414516 0x00007fc297d2f2c0: <fatal> (process::ProcessMain.cpp@139) could not acquire instance lock "../data/broker.lock"
data/broker.lock
が残っているとエラーが発生するので手動で削除してください
$ rm -fr ../data/broker.lock
RESTの起動
続いてRESTを起動します。
RESTはclient
フォルダ内のrest
をそのまま使います。
別のターミナルを開いて、rest
を_build
フォルダへコピーします。
$ cp -r ../../rest .
設定変更
そのままではrestが正常に動かないので何箇所か修正します。
src/index.js
で参照しているresources/rest.json
までのパスが相対パスだと読み込みができないので絶対パスへ変更します。(各々の環境に合わせてパスを設定してください)
/*
* Copyright (c) 2016-2019, Jaguar0625, gimre, BloodyRookie, Tech Bureau, Corp.
* Copyright (c) 2020-present, Jaguar0625, gimre, BloodyRookie.
* All rights reserved.
*
* This file is part of Catapult.
*
* Catapult is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Catapult is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Catapult. If not, see <http://www.gnu.org/licenses/>.
*/
const catapult = require('./catapult-sdk/index');
const { createConnectionService } = require('./connection/connectionService');
const { createZmqConnectionService } = require('./connection/zmqService');
const CatapultDb = require('./db/CatapultDb');
const dbFormattingRules = require('./db/dbFormattingRules');
const routeSystem = require('./plugins/routeSystem');
const allRoutes = require('./routes/allRoutes');
const bootstrapper = require('./server/bootstrapper');
const formatters = require('./server/formatters');
const messageFormattingRules = require('./server/messageFormattingRules');
const sshpk = require('sshpk');
const winston = require('winston');
const fs = require('fs');
const createLoggingTransportConfiguration = loggingConfig => {
const transportConfig = Object.assign({}, loggingConfig);
// map specified formats into a winston function
delete transportConfig.formats;
const logFormatters = loggingConfig.formats.map(name => winston.format[name]());
transportConfig.format = winston.format.combine(...logFormatters);
return transportConfig;
};
const configureLogging = config => {
const transports = [new winston.transports.File(createLoggingTransportConfiguration(config.file))];
if ('production' !== process.env.NODE_ENV)
transports.push(new winston.transports.Console(createLoggingTransportConfiguration(config.console)));
// configure default logger so that it adds timestamp to all logs
winston.configure({
format: winston.format.timestamp(),
transports
});
};
const validateConfig = config => {
if (config.crossDomain && (!config.crossDomain.allowedHosts || !config.crossDomain.allowedMethods))
throw Error('provided CORS configuration is incomplete');
};
const loadConfig = () => {
let configFiles = process.argv.slice(2);
if (0 === configFiles.length)
- configFiles = ['../resources/rest.json'];
+ configFiles = ['/home/xxx/symbol/client/catapult/_build/rest/resources/rest.json'];
let config;
configFiles.forEach(configFile => {
winston.info(`loading config from ${configFile}`);
const partialConfig = JSON.parse(fs.readFileSync(configFile, 'utf8'));
if (config) {
// override config
catapult.utils.objects.checkSchemaAgainstTemplate(config, partialConfig);
catapult.utils.objects.deepAssign(config, partialConfig);
} else {
// primary config
config = partialConfig;
}
});
validateConfig(config);
return config;
};
const createServiceManager = () => {
const shutdownHandlers = [];
return {
pushService: (object, shutdownHandlerName) => {
shutdownHandlers.push(() => { object[shutdownHandlerName](); });
},
stopAll: () => {
while (0 < shutdownHandlers.length)
shutdownHandlers.pop()();
}
};
};
const connectToDbWithRetry = (db, config) => catapult.utils.future.makeRetryable(
() => db.connect(config.url, config.name, config.connectionPoolSize, config.connectionTimeout),
config.maxConnectionAttempts,
(i, err) => {
const waitTime = (2 ** (i - 1)) * config.baseRetryDelay;
winston.warn(`db connection failed, retrying in ${waitTime}ms`, err);
return waitTime;
}
);
const createServer = config => {
const modelSystem = catapult.plugins.catapultModelSystem.configure(config.extensions, {
json: dbFormattingRules,
ws: messageFormattingRules
});
return {
server: bootstrapper.createServer(config, formatters.create(modelSystem.formatters), config.throttling),
codec: modelSystem.codec
};
};
const registerRoutes = (server, db, services) => {
// 1. create a services view for extension routes
const servicesView = {
config: {
network: services.config.network,
pageSize: {
min: services.config.db.pageSizeMin || 10,
max: services.config.db.pageSizeMax || 100,
default: services.config.db.pageSizeDefault || 20
},
apiNode: services.config.apiNode,
websocket: services.config.websocket,
numBlocksTransactionFeeStats: services.config.numBlocksTransactionFeeStats,
deployment: services.config.deployment,
uncirculatingAccountPublicKeys: services.config.uncirculatingAccountPublicKeys,
nodeMetadata: services.config.nodeMetadata
},
connections: services.connectionService
};
// 2. configure extension routes
const { transactionStates, messageChannelDescriptors } = routeSystem.configure(services.config.extensions, server, db, servicesView);
// 3. augment services with extension-dependent config and services
servicesView.config.transactionStates = transactionStates;
servicesView.zmqService = createZmqConnectionService(services.config.websocket.mq, services.codec, messageChannelDescriptors, winston);
// 4. configure basic routes
allRoutes.register(server, db, servicesView);
};
(() => {
const config = loadConfig();
configureLogging(config.logging);
winston.verbose('finished loading rest server config', config);
// Loading and caching certificates.
config.apiNode = {
...config.apiNode,
certificate: fs.readFileSync(config.apiNode.tlsClientCertificatePath),
key: fs.readFileSync(config.apiNode.tlsClientKeyPath),
caCertificate: fs.readFileSync(config.apiNode.tlsCaCertificatePath)
};
const nodeCertKey = sshpk.parsePrivateKey(config.apiNode.key);
config.apiNode.nodePublicKey = nodeCertKey.toPublic().part.A.data;
const network = catapult.model.networkInfo.networks[config.network.name];
if (!network) {
winston.error(`no network found with name: '${config.network.name}'`);
return;
}
const serviceManager = createServiceManager();
const db = new CatapultDb({
networkId: network.id,
// to be removed when old pagination is not used anymore
// json settings should also be moved from config.db to config.api or similar
pageSizeMin: config.db.pageSizeMin,
pageSizeMax: config.db.pageSizeMax
});
serviceManager.pushService(db, 'close');
winston.info(`connecting to ${config.db.url} (database:${config.db.name})`);
connectToDbWithRetry(db, config.db)
.then(() => {
winston.info('registering routes');
const serverAndCodec = createServer(config);
const { server } = serverAndCodec;
serviceManager.pushService(server, 'close');
const connectionConfig = {
apiNode: config.apiNode
};
const connectionService = createConnectionService(connectionConfig, winston.verbose);
registerRoutes(server, db, { codec: serverAndCodec.codec, config, connectionService });
winston.info(`listening on port ${config.port}`);
server.listen(config.port);
})
.catch(err => {
winston.error('rest server is exiting due to error', err);
serviceManager.stopAll();
});
process.on('SIGINT', () => {
winston.info('SIGINT detected, shutting down rest server');
serviceManager.stopAll();
});
})();
続いて、rest/resources/rest.json
の修正を行います。
まずsymbol-network
で作成した設定ファイル(nemesis-target/gateways/rest-gateway
フォルダ)をコピーします。
$ cp -r ../nemesis-target/gateways/rest-gateway/* resources/
コピーしたrest.json
を以下のように修正します。
{
"network": {
"name": "testnet",
"description": "My Company Testnet Network"
},
"port": 3000,
"protocol": "HTTP",
- "sslKeyPath": "/symbol-workdir/restSSL.key",
+ "sslKeyPath": "",
- "sslCertificatePath": "/symbol-workdir/restSSL.crt",
+ "sslCertificatePath": "",
"crossDomain": {
"allowedHosts": [
"*"
],
"allowedMethods": [
"GET",
"POST",
"PUT",
"OPTIONS"
]
},
"uncirculatingAccountPublicKeys": [],
"extensions": [
"accountLink",
"aggregate",
"lockHash",
"lockSecret",
"mosaic",
"metadata",
"multisig",
"namespace",
"receipts",
"restrictions",
"transfer"
],
"db": {
- "url": "mongodb://db:27017/",
+ "url": "mongodb://127.0.0.1:27017/",
"name": "catapult",
"pageSizeMin": 10,
"pageSizeMax": 100,
"maxConnectionAttempts": 15,
"baseRetryDelay": 750,
"connectionPoolSize": 10
},
"apiNode": {
- "host": "node",
+ "host": "127.0.0.1",
"port": 7900,
- "tlsClientCertificatePath": "/symbol-workdir/api-node-config/cert/node.crt.pem",
+ "tlsClientCertificatePath": "/home/xxx/symbol/client/catapult/_build/rest/resources/api-node-config/cert/node.crt.pem",
- "tlsClientKeyPath": "/symbol-workdir/api-node-config/cert/node.key.pem",
+ "tlsClientKeyPath": "/home/xxx/symbol/client/catapult/_build/rest/resources/api-node-config/cert/node.key.pem",
- "tlsCaCertificatePath": "/symbol-workdir/api-node-config/cert/ca.cert.pem",
+ "tlsCaCertificatePath": "/home/xxx/symbol/client/catapult/_build/rest/resources/api-node-config/cert/ca.cert.pem",
"timeout": 1000,
- "networkPropertyFilePath": "/symbol-workdir/api-node-config/config-network.properties",
+ "networkPropertyFilePath": "/home/xxx/symbol/client/catapult/_build/rest/resources/api-node-config/config-network.properties",
- "nodePropertyFilePath": "/symbol-workdir/api-node-config/config-node.properties",
+ "nodePropertyFilePath": "/home/xxx/symbol/client/catapult/_build/rest/resources/api-node-config/config-node.properties",
- "inflationPropertyFilePath": "/symbol-workdir/api-node-config/config-inflation.properties"
+ "inflationPropertyFilePath": "/home/xxx/symbol/client/catapult/_build/rest/resources/api-node-config/config-inflation.properties"
},
"websocket": {
"mq": {
"host": "broker",
"port": 7902,
"monitorInterval": 500,
"connectTimeout": 10000,
"monitorLoggingThrottle": 60000,
"maxSubscriptions": 300
},
"allowOptionalAddress": true
},
"throttling": {
"burst": 80,
"rate": 60
},
"logging": {
"console": {
"formats": [
"colorize",
"simple"
],
"level": "verbose",
"handleExceptions": true
},
"file": {
"formats": [
"prettyPrint"
],
"level": "verbose",
"handleExceptions": true,
- "filename": "/symbol-workdir/logs/catapult-rest.log",
+ "filename": "/home/xxx/symbol/client/catapult/_build/rest/logs/catapult-rest.log",
"maxsize": 20971520,
"maxFiles": 100
}
},
"numBlocksTransactionFeeStats": 300,
"deployment": {
"deploymentTool": "symbol-bootstrap",
"deploymentToolVersion": "1.1.10",
"lastUpdatedDate": "2023-12-29"
}
}
(各々の環境に合わせてパスを設定してください)
REST起動
$ npm run start
> symbol-api-rest@2.4.3 start
> node src/index.js
[winston] Attempt to write logs with no transports, which can increase memory usage: {"message":"loading config from /home/xxx/src/symbol/client/catapult/_build/rest/resources/rest.json","level":"info"}
(node:569738) [DEP0111] DeprecationWarning: Access to process.binding('http_parser') is deprecated.
(Use `node --trace-deprecation ...` to show where the warning was created)
info: loading config from /home/xxx/src/symbol/client/catapult/_build/rest/resources/rest.json
verbose: finished loading rest server config {"apiNode":{"host":"node","inflationPropertyFilePath":"/home/xxx/src/symbol/client/catapult/_build/rest/resources/api-node-config/config-inflation.properties","networkPropertyFilePath":"/home/xxx/src/symbol/client/catapult/_build/rest/resources/api-node-config/config-network.properties","nodePropertyFilePath":"/home/xxx/src/symbol/client/catapult/_build/rest/resources/api-node-config/config-node.properties","port":7900,"timeout":1000,"tlsCaCertificatePath":"/home/xxx/src/symbol/client/catapult/_build/rest/resources/api-node-config/cert/ca.cert.pem","tlsClientCertificatePath":"/home/xxx/src/symbol/client/catapult/_build/rest/resources/api-node-config/cert/node.crt.pem","tlsClientKeyPath":"/home/xxx/src/symbol/client/catapult/_build/rest/resources/api-node-config/cert/node.key.pem"},"crossDomain":{"allowedHosts":["*"],"allowedMethods":["GET","POST","PUT","OPTIONS"]},"db":{"baseRetryDelay":750,"connectionPoolSize":10,"maxConnectionAttempts":15,"name":"catapult","pageSizeMax":100,"pageSizeMin":10,"url":"mongodb://127.0.0.1:27017/"},"deployment":{"deploymentTool":"symbol-bootstrap","deploymentToolVersion":"1.1.10","lastUpdatedDate":"2023-12-29"},"extensions":["accountLink","aggregate","lockHash","lockSecret","mosaic","metadata","multisig","namespace","receipts","restrictions","transfer"],"logging":{"console":{"formats":["colorize","simple"],"handleExceptions":true,"level":"verbose"},"file":{"filename":"/home/xxx/src/symbol/client/catapult/_build/rest/logs/catapult-rest.log","formats":["prettyPrint"],"handleExceptions":true,"level":"verbose","maxFiles":100,"maxsize":20971520}},"network":{"description":"My Company Testnet Network","name":"testnet"},"numBlocksTransactionFeeStats":300,"port":3000,"protocol":"HTTP","sslCertificatePath":"","sslKeyPath":"","throttling":{"burst":80,"rate":60},"timestamp":"2023-12-30T14:23:09.703Z","uncirculatingAccountPublicKeys":[],"websocket":{"allowOptionalAddress":true,"mq":{"connectTimeout":10000,"host":"broker","maxSubscriptions":300,"monitorInterval":500,"monitorLoggingThrottle":60000,"port":7902}}}
info: connecting to mongodb://127.0.0.1:27017/ (database:catapult) {"timestamp":"2023-12-30T14:23:09.725Z"}
verbose: connecting to mongo at mongodb://127.0.0.1:27017/catapult {"timestamp":"2023-12-30T14:23:09.772Z"}
info: registering routes {"timestamp":"2023-12-30T14:23:09.773Z"}
info: Using protocol: HTTP {"timestamp":"2023-12-30T14:23:09.788Z"}
info: listening on port 3000 {"timestamp":"2023-12-30T14:23:09.800Z"}
上記のようなログが表示されたら成功です。
IP:3000/node/info
のようにREST APIへアクセスできます。
参考