まだタイトルはありません。

まだタイトルはないのです。

NEM-sdkを使ってオフラインで署名して、オンラインでアナウンスする。

オフラインで簡単に署名できない暗号通貨なんて使いたくないですよね?そんなものは危なくて使えたもんじゃないとみなさんお思いになられているかと思います。取引所、webウォレットはもちろんのこと、オンラインにしているデスクトップクライアントウォレットでさえ不安なことでしょう...。
そこで、NEM-sdkを利用して、オフラインで署名した取引を作成するプログラムと、それをアナウンスするプログラムを書いてみました。
プログラミングなんか興味ないや、コード読みたくないや、という方は最後の、「NEMのいいところ」だけ読んでいただければと思います!

Github: nem_offline

github.com

準備

環境

NEM-sdk
node.js
javascrpt

ディレクトリ構造

offlineSigner
├── key.json
├── node_modules
├── offlineSigner.js
├── package-lock.json
├── sender.js
└── serializedTransaction

sdkをinstall

NEM-sdk: GitHub - QuantumMechanics/NEM-sdk: NEM Developer Kit for Node.js and the browser
プロジェクトディレクトリ(offlineSigner)で npm install nem-sdkしてNEM-sdkをインストールしておきます。
これでファイル内で

var nem = require("nem-sdk").default;

することで、sdkが使えるようになります。

signer.js

アドレス生成

まずはオフラインで署名するスクリプトを書きましょう。
が、秘密鍵がないと署名もなにもないので、アドレスも生成し、別ファイルに保存しておきます。
①ネットワークIDでテストネット、メインネット、Mijinから任意のIDを指定します。
秘密鍵を生成しペアとなる公開鍵を生成
③公開鍵からアドレスを生成

  var networkId = -104;  // test net = -104
  var rBytes = nem.crypto.nacl.randomBytes(32);
  var privateKey = nem.utils.convert.ua2hex(rBytes);
  var keyPair = nem.crypto.keyPair.create(privateKey);
  var publicKey = keyPair.publicKey.toString();
  var address = nem.model.address.toAddress(publicKey, networkId);

commonオブジェクトの作成

commonオブジェクトは秘密鍵から生成します。

var private_key = PRIVATE KEY
var common = nem.model.objects.create("common")("", private_key);

取引の作成(transaction entiry)

nem.model.objects.createを利用。
送金先(recipient)、送金量(amount)、NEMではメッセージも指定することができます。

var transferTransaction = nem.model.objects.create("transferTransaction")(recipient, amount, message);
var entity = nem.model.transactions.prepare("transferTransaction")(common, transferTransaction, nem.model.network.data.testnet.id);

署名

nem.model.transaction.sendを利用して送金しようとすると、秘密鍵から作られるcommonオブジェクトが必要になってしまいます。
オンラインで秘密鍵を扱いたくないため、オフラインで署名済み取引を生成し、それをネットワークに送信するようにします。
①nem.model.transaction.send内の処理のうち、署名部分をSign functionとして利用。
取引の内容を保持するentityに秘密鍵から作られたcommonオブジェクトで署名しています。

function sign(common, entity) {
    if(!entity || !common) throw new Error('Missing parameter !');
    if (common.privateKey.length !== 64 && common.privateKey.length !== 66) throw new Error('Invalid private key, length must be 64 or 66 characters !');
    if (!nem.utils.helpers.isHexadecimal(common.privateKey)) throw new Error('Private key must be hexadecimal only !');
    let kp = nem.crypto.keyPair.create(nem.utils.helpers.fixPrivateKey(common.privateKey));
    let result = nem.utils.serialization.serializeTransaction(entity);
    let signature = kp.sign(result);
    let obj = {
      'data': nem.utils.convert.ua2hex(result),
      'signature': signature.toString()
    };
    return obj
}

sender.js

nem.com.requests.trasaction.announceで先ほど作った署名済み取引をネットワークにアナウンスします。
signをオフラインpcで実行し、USBなどで署名済み取引をオンラインpcにもってきてアナウンスするという形がシンプルです。が、署名済み取引をQRにしスマホで読み込むとか便利でいいですね。最近そんなようなの誰かがつくってると聞いたよう聞かないような...。
NEM Hot/Cold Wallet: The First Ever NEM Cold Offline Wallet You Can Use To Send And Receive Funds - Blog Posts - NEM Forum

)

function announce(endpoint) {
  fs.readFile('./serializedTransaction', 'utf8', (err, file) => {
    var obj = file
    nem.com.requests.transaction.announce(endpoint, obj).then(function(res) {
        console.log("announced!");
    });
  });
};

このプロジェクトの今後

秘密鍵ファイルの暗号化
マルチシグ対応
アポスティーユ対応
コマンドラインツール化
などをしたいですが...
あまりJavascriptは好きではないのでやる気がないです。

nem-toolchain | Command line toolchain for NEM blockchain

というのがあるようなのでgoがかけるなら(書けるようになって)こっちを手伝いたいなぁと思っております。

NEMのいいところ

アドベントカレンダー用の記事ということで...

私はBitcoinから暗号通貨の世界に踏み込みましたが、Bitcoinに関連したプログラムを作成することはハードルが高かったです。もちろんエンジニアではないからですが...。
しかし、NEMは私のような素人でも簡単にプログラムを書くことができます。
NEMに触れるようになって、実際にプログラムを書くようになりました。
コードを読むようになりました。
偉そうに開発者に質問したり、バグを報告したりするようになりました。
私にとってNEMは新しい世界に踏み込むきっかけとなりました。
そしてこの世界は楽しいです。常に新しいことであふれています。これさえあれば生きていけると皆さん思っておられることでしょう。
なにを迷うことがあるのでしょうか。今日から取引なんてくだらないとこはやめて開発しましょう。 (取引していることが暗号通貨にとって不要だと言っているわけではない。でも、取引はあなたがやらなくても誰かが絶対やってくれます!)
取引している暇があったら調査です。
取引している暇があったら開発です。

なぜならば....。

だからです。
本物にするのは開発者です。
一般人から見れば草コインもNEMも同じ詐欺に見えるでしょう。
なにが違いを生じるとすれば、それは取引している人によってではなく、開発している人によってです。

そしてこの言葉も心に刻みましょう。

Talk of tech innovation is bullsh*t. Shut up and get the work done (by Linus Torvalds) 偉そうに語ってないで、さっさとやることやれ。

Talk of tech innovation is bullsh*t. Shut up and get the work done – says Linus Torvalds • The Register