2021/12/04
tmkmsをdockerでビルドしてローカルのdocker-compose環境で利用してみる
tendermintcosmos-sdkrustdocker
概要
iqlusioninc/tmkmsのDockerfileを作成して、docker-composeで動かせるようにしました。
tmkmsとは
iqlusioninc/tmkmsはtendermintというコンセンサスアルゴリズムの署名管理に使うことができます。
主に以下の用途で使われます
- プライベートキー保管のセキュリティ強化
- 2重署名の回避
プライベートキー保管のセキュリティ強化
ハードウォレットのキーを署名に利用することができようになります。
プライベートキーをハードディスクやSSDなどのローカルデバイスではなく、セキュリティレベルの高いUSBデバイスであるハードウェアウォレット上に(のみ)保管できます。
これによってプライベートキーの読み取りへのハードルが上がり、ノードの運用者と鍵の管理者を分離することができるようになります。(もちろん単純にハッキングされた時の耐性が高くなるというメリットもあります。)
2重署名を回避できる
- (tendermintでは)2重署名を行ってしまうと、コンセンサスを形成しようとしているネットワークに害を及ぼしてしまいます。(ビザンチンな振る舞いと認定されます)
- cosmos-sdkなどのtendermintを利用しているブロックチェーンでは、そのような振る舞いが特定されるとペナルティ(stakingしているトークンを失う等)が課せられます。
- また、cosmos-sdkでは2重署名だけでなく、nodeが停止して、コンセンサスに対する貢献行動が一定時間停止した場合にも似たようなペナルティが発生します。
- 従って、コンセンサスを行うノード(バリデーターノードと呼びます)の可用性を高めようとする動機が生まれます。(複数サーバーで運用したり)
- 複数サーバーで運用したりすると、どうしても2重署名しやすくなりますので、それを回避しようとするために使います。
Dockerfile
以下の内容で、docker imageをビルドします。
カスタマイズポイントとしては以下のようなものになります。
- RUST_VERSION(1.54.0ですが、1.46以降であれば良いようです。)
- TMKMS_VERSION(現状では0.10.1が最新)(ここを変更したらTMKMS_SRC_SHA256も変更する必要があります。)
ca-certificates
やbash
は入れる必要がありませんが、度々利用するので入れています。
# @see https://github.com/rust-lang/docker-rust
FROM alpine:3.14 as builder
# install utilities
RUN apk add --update alpine-sdk cmake clang libusb-dev
RUN apk add --no-cache ca-certificates
ENV RUSTUP_HOME=/usr/local/rustup \
CARGO_HOME=/usr/local/cargo \
PATH=/usr/local/cargo/bin:$PATH \
RUST_VERSION=1.54.0 \
TMKMS_VERSION=0.10.1 \
TMKMS_SRC_SHA256=184f483c09a9cfcada58fe6aa3c0370dba0c8ff38df5d264fca5a1cc1033b602
RUN set -eux; \
apkArch="$(apk --print-arch)"; \
case "$apkArch" in \
x86_64) rustArch='x86_64-unknown-linux-musl'; rustupSha256='bdf022eb7cba403d0285bb62cbc47211f610caec24589a72af70e1e900663be9' ;; \
aarch64) rustArch='aarch64-unknown-linux-musl'; rustupSha256='89ce657fe41e83186f5a6cdca4e0fd40edab4fd41b0f9161ac6241d49fbdbbbe' ;; \
*) echo >&2 "unsupported architecture: $apkArch"; exit 1 ;; \
esac; \
url="https://static.rust-lang.org/rustup/archive/1.24.3/${rustArch}/rustup-init"; \
wget "$url"; \
echo "${rustupSha256} *rustup-init" | sha256sum -c -; \
chmod +x rustup-init; \
./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host ${rustArch}; \
rm rustup-init; \
chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \
rustup --version; \
cargo --version; \
rustc --version;
# build from source
WORKDIR /tmkms
RUN set -ex; \
wget https://github.com/iqlusioninc/tmkms/archive/refs/tags/v${TMKMS_VERSION}.tar.gz -O tmkms.tar.gz; \
echo "${TMKMS_SRC_SHA256} /tmkms/tmkms.tar.gz" | sha256sum -c -; \
tar -zxvf "tmkms.tar.gz"; \
rm -f tmkms.tar.gz; \
mv tmkms-${TMKMS_VERSION} src; \
cd src; \
cargo build --release --features=softsign;
FROM alpine:3.14
COPY --from=builder /tmkms/src/target/release/tmkms /usr/local/bin/tmkms
RUN chmod +x /usr/local/bin/tmkms
# Install ca-certificates
RUN apk add --update ca-certificates
# install utilities
RUN apk add bash
ARG USER_ID
ARG GROUP_ID
ENV HOME /tmkms
ENV USER_ID ${USER_ID:-1000}
ENV GROUP_ID ${GROUP_ID:-1000}
# add our user and group first
RUN addgroup -g ${GROUP_ID} tmkms; \
adduser -D -u ${USER_ID} -G tmkms -h /tmkms -s "/bin/bash" tmkms;
# install su-exec
RUN apk add --no-cache su-exec; \
su-exec tmkms true;
WORKDIR /tmkms
EXPOSE 26658
CMD ["tmkms", "start"]
事前準備
docker-compose
で動かす前に色々と準備します。
上記のDockerfile
をビルドしてtmkms:latest
のimageを作っておきます。
$ docker build -t tmkms:latest -f Dockerfile .
次に、事前にconfigファイルなどを作成します。
% docker run -it --rm -v $(pwd)/.docker-data/tmkms:/tmkms/.tmkms tmkms:latest bash
# container内で以下を実行します。
$ tmkms init -n cosmoshub /tmkms/.tmkms
# 必要に応じて、 `tmkms softsign import` したり `tmkms softsign keygen` したりします。
# また必要に応じて、/tmkms/.tmkms/tmkms.tomlも編集していきます。
/tmkms/.tmkms/tmkms.tomlを自分のノードの内容に応じて編集します。
[[chain]]
id = "my-chain"
key_format = { type = "bech32", account_key_prefix = "xxpub", consensus_key_prefix = "xxconspub" }
state_file = "/tmkms/.tmkms/state/my-chain-consensus.json"
[[providers.softsign]]
chain_ids = ["my-chain"]
key_type = "consensus"
path = "/tmkms/.tmkms/secrets/your-validator-secret.key"
[[validator]]
addr = "tcp://192.168.10.2:26658"
chain_id = "my-chain"
secret_key = "/tmkms/.tmkms/secrets/secret_connection.key"
protocol_version = "v0.34"
reconnect = true
docker-compose
以下のような感じになりました。
- validatorに指定しているプログラムはtendermintベースの任意のバリデータノードプログラムを想定しています。(実際にはgaiadなどを指定します)
version: '3'
services:
tmkms:
container_name: tmkms
image: "tmkms:latest"
command: >
tmkms start -c /tmkms/.tmkms/tmkms.toml
ports:
- "26659:26658"
volumes:
- .docker-data/tmkms:/tmkms/.tmkms
networks:
localnet:
ipv4_address: 192.168.10.1
validator:
container_name: validator
image: "your-sample-tendermint-validator:latest"
command: >
your-daemon start
ports:
- "26658:26658"
volumes:
- .docker-data/validator:/your-daemon/.your-daemon
networks:
localnet:
ipv4_address: 192.168.10.2
depends_on:
- tmkms
networks:
localnet:
driver: bridge
ipam:
driver: default
config:
-
subnet: 192.168.10.0/16
これらの設定で、ローカル環境でtmkmsを活用したバリデータノードのテスト環境の構築が確認できました。
以上です。
関連する記事
Concordiumノードをローカルで動かしてみた
Concordiumの調査のために、ローカルでソースコードをビルドしてノードを動かしてみました
[Rust]axumとdragonflyを使ったWebsocket Chatのサンプル実装
redis互換のdragonflyをPUBSUBとして利用して、Websocket Chatアプリのサンプル実装を行いました。
[Rust]TiDBを使ったサンプルアプリケーションの実装
RustからTiDBを使ったアプリケーションの実装を行いました。
[Rust]Google Cloud Storageを利用する
GCSやNFSのファイルを扱えるpackageをRustで実装しました。