LDKとWASMを使ってNode-REDのカスタムノードを作ってみた
みなさんはNode-REDというローコード・ノーコード開発環境をご存知ですか。
Umbrelにも入っているOSSで、フローチャートのような形式でプログラムを記述できる面白いブラウザベースの環境です。大学生の頃、夏休みに母校で中学生にサーバーサイドの簡易なプログラミングを教えるのに使ったこともあり、愛着があります。
↑こんな感じ。小学生に定番のScratchのような直感的さがあります。線で繋がっている小さなプログラムを「ノード」と呼び、様々な種類の処理ができます。
Node-REDはその名の通りNodeJSで記述されており、「関数」ノードを使えば普通にJavascriptを記述したノードを作ることができます。デフォルトで入っている数十種類のノードで実現できない機能はこのように「関数」ノードで実装できるほか、独自にカスタムノードを作成して公開することもできます。(4600種類近くあるようですが、どれくらいが使い物になるかは知りません)
例えばLNDなどのAPIを叩くノードなどはJavascriptのライブラリが存在するので比較的簡単に作れてしまうでしょう。ところが、最近のライトニングのトレンドはLDKを使ったブラウザウォレットやブラウザベースのアプリではないでしょうか。
LDKの何よりの特徴はWASM (WebAssembly)と呼ばれる、ブラウザ内で動作するバイナリコードに組み込むことができる点です。Rust-lightningの高速で厳密なコードをブラウザ内のアプリケーションに組み込めることには安全性やパフォーマンスの面で大きなメリットがあります。
そこで、Node-REDでもWASMを使ったカスタムノードが作れるのか調べてみたところ、先例がありました:
今回はこの先例に沿って、WASMにはLDKの一部であるlightning-invoiceライブラリを使ったものを開発して遊んでみることにしました。
結論から言えばできました。
invoice-amountノード
GitHubにコードを全てアップしています。自分でもやってみたい人はそっちとREADME.mdを参照してもらったほうが具体的に書いてます。
概要を説明すると、
1. Cargo newでRustプロジェクトを作る
2. Cargo.tomlをWASM向けにいじる。必要なライブラリを追加する
3. コードを書く。(WASMで受け取れるのはi32, i64, f32, f64の4種類と&[u8]みたいなバイト配列みたい?返せるものもたぶん同じ)
4. WASMにコンパイルして、その後JSバインディングを生成する。
5. プロジェクトルートに新しいディレクトリを作り、その中でnpm initする。package.json、node-name.js、node-name.htmlを先例や公式を参考に作る。Node-name.jsはカスタムノードのロジックを担うので、その中からWASM内の関数を呼び出す。(JSバインディングをモジュールとして読み込む)
6. 完成したらNode-REDのディレクトリへとnpm installする。Node-REDを再起動すると、WASMを使ったカスタムノードが追加されている!
lnbc7843490p1pj03y0gsp56z92dsxl4e3k9xtz4zwfqn5cn57rthzfmzlqyqx9ng55q5qmty0qpp5xd58d43zde0vxlr04nzsu38y2zhw0s6zc85h49n0kp08t4tml6lsdphgfkx7cmtwd68yetpd5s9xct5v4kxc6t5v5s9gunpdeek66tnwd5k7mscqpjrzjqdhhw4tgwax9e4uczpa2ws4kj0mk96g9zvxyam4x4d4dz9gufjl85zm2xuqq8pcqqyqqqqqqqqqqq9gq9q9qyysgqhe0673slenjmzagurtmpkvcty36l90yr6zmde0cdrhys8runu78h8hrxcc23la38tgk5802s4fvfzq73jjdgp02ngeucsqq96kwwkqqp8ej2h5 でテスト。
lnbc1234567890n1pj03ye0pp5dxd2xhz8sv07hk5wf7tz23tngrcn45rx2fkmuvs7cpuxaph4f8lqdqqcqzzsxqyz5vqsp5fcup0xm03hj46de0y6vl5es0g4grqfw6n9gd00uahysrg7wxlprq9qyyssq52kzv4fzm7supfyl5xc3teavx40rdhxkas4q0hdmdla4s9jkad8ku3jtdfsyxym5kmzs5j6h5ysg64eduedu7jah9xvtfzwudafxq6spuaggtt でテスト。
(後者はi32だとmsat数がi32::MAXを超えて失敗するがi64なので大丈夫)