2025年9月、SymbolチェーンにHFを伴う大きなアップデートがありました。
今回のアップデートではその重大性から symbol-bootstrap にも特例で修正が入ると聞きました。
これを聞いた時「あ、このままだと一定のノードはアップデートできずマズいかも。。。」と思い、先回りしてその問題を解決すべく動きました。
結果として、私とさだかね(@ccharvestersha)さんでバグ対応のPull Requestを出すことになりました。
この記事では、そのうち私が担当した「暗号化ライブラリの互換性問題」への対応について書きます。
問題の背景
違和感は2年前から
2023年末、ちょっとノードの構成を変更したくてbootstrapで運用してたサーバーでいくつかコマンドを打っていたのですがなぜかパスワードが正しいはずなのに間違っているとわれて何も出来ない事象が発生しました。
急ぎではなかったので当時放っておいたのですがしばらく経っても解決せず困惑した際のツイートがこちら↓
当時どうやって対応したのかは覚えてないですが、以下のどれかで対応したと思います。
- 問題は暗号化された
target/addresses.ymlの復号時に発生してそう - 自分が運用しているノードのうち、問題なく復号できるサーバーもある
- 対応1: 別のノードに問題の
addresses.ymlを持っていって復号 - 対応2: 平文で別途保存していた
address.ymlを該当のノードで暗号化 - 上記のどちらでも解決した
しばらくして原因が判明
コミュニティのメンバーとTwitter上でやり取りしていくうえでなんとなく原因がわかってきました。
symbol-bootstrapの config compose start などaddresses.ymlの内容を読むコマンドでは、暗号・復号するのに crypto-js というnode系の暗号化ライブラリが使われています。
それも当時はbootstrapが直接 crypto-js 直接使っているのではなく、以下のようにsymbol-sdk経由でcrypto-jsを呼び出していました。
問題の根本
原因1: symbol-sdkのcryoto-jsのバージョン指定が曖昧だった
{
"dependencies": {
"crypto-js": "^4.0.0" // これ
}
}
普段Node.jsを扱ってる方ならピンと来ると思いますが、この ^4.0.0 という書き方は4.0.0以上 5.0.0未満のバージョンの中で最新のものをインストールする という書き方です。
※実際にpackage.jsonで指定されていたバージョンは違うかもしれませんが例として。
原因2: crypto-jsに破壊的アップデートがあった
crypto-jsは直近で以下のアップデートがされています。
- 2022-07-22 v4.1.1 リリース ← ここまでは過去verと互換性あり
- 2023-10-24 v4.2.0 リリース ← 4.1.1と互換性がない!
つまり
- 2023-10-24以前からsymbol-bootstrapでノードを運営していた
-
addresses.ymlはcrypto-js@4.1.1で暗号化されている
-
- 2023-10-24以降にsymbol-bootstrapをインストールし直したり、新しいサーバーに移行した(
npm install相当の処理を行った)- 暗号化された
addresses.ymlをcrypto-js@4.2.0の方式で復号しようとした
- 暗号化された
- エラー内容も
パスワードが間違っています的なメッセージしか出ないため原因がわからない
このせいで本人が気づかないうちに互換性のないcrypto-jsが内部で使われてしまっていたので、正しいパスワードを入れても復号が出来ず、エラーとなっていました。
補足
なお、マイナーアップデートの状態でここまで破壊的な変更が入るとは普通は想像しないので、symbol-sdkがこのようなバージョン指定だったことに問題はなかったと個人的には思っています。
対応した内容
上記の問題から、このまま公式のsymbol-bootstrapの修正版が配布されると、アップデート時に「Cannot decrypt file」エラーで秘密鍵が読み出せなくなる運営者が続出することが予想されました。
そこで、コアチームがチェーン本体の修正を進めている間に、この互換性問題への対応を先行して実装することにしました。
基本方針
単にバージョンを固定するだけでは、すでに旧方式で暗号化されたファイルを持つユーザーの問題は解決しません。
そこで、既存ファイルの互換性を保ちつつ、新方式へ安全に移行できる仕組みを実装することにしました。
実装した対策は以下の3つです。
対応内容
- crypto-js@4.2.0を参照するようにバージョンを固定する
- まず、v4.2.0の方法で復号を試みる
- もしエラーになった場合、 v4.1.1の暗号化方式で複合する
- 同時に4.2.0で最暗号化したaddresses.ymlを出力する
これにより、ユーザーはコマンドを実行するだけで、ファイルの復号をやりつつ自動的に新しい方式へ移行されます。
初のOSSコントリビュート
以下のPRが無事にマージされて、新しいノードのアップデートと同時に配信されました。
fix: Add fallback decryption for crypto-js version compatibility#17
この処理は、条件に当てはまるユーザーに対して 一度だけ 実行されるものです。
そのため、ほとんどの方は特に意識することなくアップデートを終えたと思います。
もし当時ノードを更新した際に次のようなログが出力されてたら、その裏で旧方式から新方式への移行処理が静かに行われてたんだなーと思ってもらえたら幸いです
Legacy encryption detected in target/addresses.yml. Upgrading to stronger encryption...
Creating backup of original file at target/addresses.yml.bk
訳)target/addresses.yml でレガシーな暗号化が検出されました。より強力な暗号化にアップグレードしています...
target/addresses.yml.bk にある元のファイルのバックアップを作成しています
まとめ
この記事は、いわゆるポストモーテム的な意味合いも含んでいるので、最後に個人的な考えを少し書いておきます。
現在、コアチームは symbol-shoestring への移行を推奨しており、symbol-bootstrap はサポート終了が宣言されています。
これは設計思想や将来の保守性を考えれば、長期的には正しい方向性だと思います。
一方で、現実問題としては bootstrap で運営されているノードはまだ相当数存在しており、
現時点の shoestring CLI は「すぐに全面移行できる完成度か」と言われると、正直まだ難しいと感じています。
bootstrap はもともとコアチームではない個人によって作られ、結果として長い間Symbol のノード運用を実質的に支えてきました。
その役割を考えると、新しい CLI に世代交代していく流れ自体は自然なものだと思います。
ただ、移行を促すのであれば、「理想として正しい」だけでなく「現場で無理なく使える」状態になってからであってほしい、というのが率直な感想です。
来年の NEMTUS の Hack+ 2026 が一段落したあたりから、私も shoestring への移行を検討しつつ、 今度はそちら側の発展にも少し関われたらいいなと思っています。