Pebble Coding

プログラマーの作業メモ

JSONRPC をpython で体験する

RPC(リモートプロシージャコール)とはRESTと同じような、
特定フォーマットのHTTPリクエストを受け取り、レスポンスを返すプロトコルの一種です。
フォーマットには XML, JSON, protocol buffer, messagepack などあります。 最後の2つはバイナリフォーマットです。
最も簡単なjson-rpcを体験してみましょう。

環境: macOS

こちらのチュートリアルをそのまま使ってみます。

Quickstart — jsonrpc 1.10.8 documentation

pip というpython 用のパッケージマネージャー(rubyでいうところのbundle)はインストールされているものとします。

このチュートリアルで使われているパッケージをすべてインストールします。

$ pip install json-rpc
$ pip install werkzeug
$ pip install requests
$ pip install json-rpc
Collecting json-rpc
  Downloading json_rpc-1.10.8-py2.py3-none-any.whl (40kB)
    100% |████████████████████████████████| 40kB 371kB/s 
Installing collected packages: json-rpc
Successfully installed json-rpc-1.10.8
$ pip install werkzeug
Collecting werkzeug
  Downloading Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)
    100% |████████████████████████████████| 327kB 1.3MB/s 
Installing collected packages: werkzeug
Successfully installed werkzeug-0.14.1
$ pip install requests
Collecting requests
  Downloading requests-2.18.4-py2.py3-none-any.whl (88kB)
    100% |████████████████████████████████| 92kB 946kB/s 
Collecting certifi>=2017.4.17 (from requests)
  Downloading certifi-2018.1.18-py2.py3-none-any.whl (151kB)
    100% |████████████████████████████████| 153kB 675kB/s 
Collecting chardet<3.1.0,>=3.0.2 (from requests)
  Downloading chardet-3.0.4-py2.py3-none-any.whl (133kB)
    100% |████████████████████████████████| 143kB 999kB/s 
Collecting urllib3<1.23,>=1.21.1 (from requests)
  Downloading urllib3-1.22-py2.py3-none-any.whl (132kB)
    100% |████████████████████████████████| 133kB 839kB/s 
Collecting idna<2.7,>=2.5 (from requests)
  Downloading idna-2.6-py2.py3-none-any.whl (56kB)
    100% |████████████████████████████████| 61kB 889kB/s 
Installing collected packages: certifi, chardet, urllib3, idna, requests
Successfully installed certifi-2018.1.18 chardet-3.0.4 idna-2.6 requests-2.18.4 urllib3-1.22

server.py client.py を作成し、実行します。

$ python server.py 
 * Running on http://localhost:4000/ (Press CTRL+C to quit)

これを実行します。

$ python client.py 

標準出力にechoされました。

127.0.0.1 - - [15/Feb/2018 20:35:32] "POST /jsonrpc HTTP/1.1" 200 -

参考: 【Python】RPCライブラリ・フレームワークまとめ - Qiita

ビットコインにおけるブルームフィルターとマークルツリーパス

現時点(2018年2月)において2009年から作られたビットコインのブロックの数(=ブロック高)は、
こちら Bitcoinブロックエクスプローラ - ブロックチェーン をみるとわかるように、 508786 です。
最新の4つのブロックを見ると、一つのブロックには、200 ~ 1600 個のトランザクションが含まれていました。

ビットコインルノードはトランザクション情報全てを持つ必要があるため、現時点で、
500GBほどのディスクを必要としますが*1、フルノードでないビットコインノードである、
ウォレットノード、マイニングノードなどの軽量ノード(SPVノード)では、すべてのトランザクション情報を持つ必要はありません。
しかし、あるアドレスから送信、受信したあるトランザクションがどこのブロックに含まれるかを効率よく知る必要があります。
SPVノードはすべてのトランザクション情報を持つフルノードに対してトランザクションIDを送り、
ルノードは、それをすべてのブロックから検索し、見つかれば、そのトランザクションの情報をSPVノードに送り返します。
この仕組みを使えばSPVノードはすべてのトランザクション情報を持つ必要がありません。

あるトランザクションがどのブロックに含まれるか、高速に検索するには事前にインデックスをつけておけばよいです。
これを実現するための仕組みがマークルツリーパスです。

マークルツリーパス

マークルツリーパスに関してネット上に分かりやすい解説が見つからなかったので、
(マークルツリーの解説はありますが。。)
オライリーのmastering bitcoin の解説か日本語訳した無料版の資料 https://www.bitcoinbook.info/translations-of-mastering-bitcoin/ を参照するのがよさそうです。

C++が分かる方はオリジナルソースを読むのもいいかと思います。
該当ロジック部分だけであれば、量的にはわずかです。
GitHub - bitcoin/bitcoin: Bitcoin Core integration/staging tree

マークルツリーの実装ヘッダはこれだけです。 https://github.com/bitcoin/bitcoin/blob/master/src/merkleblock.h

マークルブロッククラスCMerkleBlockは一つのブロック内にある複数のトランザクションとその位置(マークルパス)を表現したものです。
SPVノードとフルノード間でやりとりされるのは、このクラスの値をバイナリでシリアライズしたものになります。

CMerkleBlockクラスのシリアライズしている関数の実装を見てみましょう。

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
    // トランザクションの数
    READWRITE(nTransactions);
    // トランザクションIDのarray
    READWRITE(vHash);
        
    std::vector<unsigned char> vBytes;
    if (ser_action.ForRead()) {
        // read
        READWRITE(vBytes);
        CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this));
        us.vBits.resize(vBytes.size() * 8);
        for (unsigned int p = 0; p < us.vBits.size(); p++){
            us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
        }
        us.fBad = false;
    } else {
        // write
        // トランザクションIDのarrayに対するビットOn/Offをバイトにしたもの
        vBytes.resize((vBits.size()+7)/8);
        for (unsigned int p = 0; p < vBits.size(); p++){
            vBytes[p / 8] |= vBits[p] << (p % 8);
        }
        READWRITE(vBytes);
    }
}

コメントに書いていますが、シリアライズされているのは、このクラスのメンバ変数である
nTransactions, vHash, vBits の値だけを使っています。
例えば、対象トランザクションが一つだけ、このブロックに含まれるトランザクションの数が14個の場合の構造を図にしたものがこちらです。

f:id:pebble8888:20180217111443p:plain

vBitsはそのノードの子孫に対象トランザクションが含まれる場合trueです。
vHashはそのノードの子孫に対象トランザクションが含まれない場合そのノードのハッシュです。
一番下のノードはトランザクションIDです。

CMerkleBlock の利用箇所

CMerkleBlockが利用されているのは、net_processing.cpp, rpc/rawtransaction.cpp, wallet/rpcdump.cpp の3つのソースファイルですが(残りは単体テスト), 簡単そうな、rpc/rawtransaction.cppをみてみます。

CMerkleBlock が使われているのは、以下2つの関数です。

// @param  一つのブロック内にあることを前提としたトランザクションIDの配列
// @return 指定されたトランザクションの情報を含むマークルブロックをHEX文字列にしたもの
UniValue gettxoutproof(const JSONRPCRequest& request)

// @param gettxoutproof で返されたマークルブロックHEX文字列
// @return 指定されたマークルブロックがブロックチェーンに含まれるvalidなものかどうか
UniValue verifytxoutproof(const JSONRPCRequest& request)

どちらも引数を見ると分かるようにJSONRPCのリクエストに応答を返すものです。
gettxoutproof はフルノード上で、指定したトランザクションのunspentなアウトアップトランザクションが存在するブロックを、
ブロックチェーン内を検索します。これにはディスクアクセスを必要とします。
verifytxoutproof はマークルブロック内のマークルパスのハッシュを合成したものがマークルルートハッシュに一致するかどうかを確認します。 もし、クラッカーが不正なトランザクションをこのブロックに追加されたものとして利用しようとした場合、
マークルルートハッシュが異なる値を持つので、ブロックチェーンの検証が行われた際に不正データとして破棄されます。

vHashの値に加えて、vBitsの値が必要なのは、マークルルートハッシュを計算するために、vHashをどの順番で合成していけば良いのか順序を知る必要があるためです。
ここでの例でのトランザクション数は14なので、height は4となります。
vHashの値の個数は height + 1 (=5) vBitsの値の個数は 2 * height + 1 (=9) となります。 トランザクション数が大きくなっても、heightが大きくなる速さはlog2なので、シリアライズ結果のデータサイズはそれほど大きくはならないことが分かります。

ブルームフィルター

ブルームフィルターとは、一般にはデータベースなど、大量のデータを扱う際に用いられる、インデックス手法の一種です。

ググって見つかったブルームフィルターに関する解説はこちら。

ブルームフィルタ - Wikipedia

ビットコインの技術 BloomFilter プログラミングJava

Scalable Bloom Filtersとは一体....? - Qiita

C++でブルームフィルタを実装する方法 | プログラミング | POSTD

ブルームフィルターの実装ヘッダはこれだけです。 https://github.com/bitcoin/bitcoin/blob/master/src/bloom.h

あるビットコインアドレスが現在所有してしているコイン量を知るには関連するトランザクション情報全てを全ての ブロックからとってくる必要がありますが、その検索方法だと、SPVノードからの問い合わせを受けつけるフルノードはそのSPVノードが利用しているビットコインアドレスを特定できる事になります。
これに若干の秘匿性を持たせる仕組みがブルームフィルターです。

*1:ブロックサイズは1MBなので、フルノードは 1MB* 508786 = 508GBのディスクが必要ですが、 ブロックヘッダサイズは80バイトですし、1トランザクションのサイズも数十バイトなので、SPVノードには大量のディスクは必要ありません。

2017年買ってよかったモノベスト3

2017年買ってよかったモノベスト3です。

第3位 MacBookPro 2017 13inch

www.apple.com

f:id:pebble8888:20180209203332j:plain:w300 f:id:pebble8888:20180209203345j:plain:w300

今まで、iOSアプリ開発用には MacBook Air を使っていましたが、Storyboardを開くのにメモリ不足で、
きつくなってきていたので、入手を決めました。
Storyboardを開く時に時間がかかることもなくなりました。

vim を使う際、Escキーがタッチバーなのはきついので、タッチバーなしモデルにしました。
またカフェで作業することもあるので、13inch にしました。 キーボードのタッチが MacBook Air に比べてかなり浅くなっています。
私は慣れましたが、肩こりがひどくなり、旧MacBook Proに戻したという方もいるのでしっかり確認しましょう。

USB-C 用のケーブルもいくつか購入しましたが、特に問題はありませんでした。

第2位 コードレスクリーナー Dyson V7 Fluffy

www.dyson.co.jp

f:id:pebble8888:20180209203153j:plain:w300 f:id:pebble8888:20180209203142j:plain:w300

ご存知、ダイソンのフローリング用コードレスクリーナーです。
床を掃除するのが楽しくなりました。
騒音も小さめなのが気に入っています。
女性が使うには少し重いかもしれないので、重さは店頭で確認しましょう。

第1位 コイズミ照明 KOIZUMI LED シーリング

webcatalog.koizumi-lt.co.jp

f:id:pebble8888:20180209203426j:plain:w300 f:id:pebble8888:20180209203404j:plain:w300

天井用の照明です。
少し値段がお高めですが、手元のリモコンで、昼間は寒色、夜は暖色に変更でき、消灯、点灯も可能です。
さらに、リモコンでオフした後、壁のスイッチをオフ、オンすると点灯するのが便利です。

クラウドマイニング HashFlare で SHA256 (BTC) にいくらか突っ込んでみた(2018年2月)

クラウドマイニングやってみたいなーという簡単な気持ちで、HashFlare のSHA256 (BTC) に少額を突っ込んでみました。
HashFlareはスコットランドの会社らしいです。

メリット、デメリット

マイニング機材の購入維持、マシンの騒音を気にする必要がないというのが、
自前マイニングに対するメリットです。
逆にマイニング会社の倒産、盗難などがデメリットになります。

購入

買ったのはコレ、SHA256 つまり、ビットコイン(BTC)のマイニングです。

f:id:pebble8888:20180203111639p:plain:w200

クレジットカードで日本円、又はBTCで購入することもできます。
期限は1年間で一括払いです。
購入予約をして、支払いするとそれが完了するようになっています。
支払いしないと、数時間でキャンセル扱いになるようです。

2 TH/s 分を購入してみました。
お値段は 10 GH/s で$2.2なので、
2000GH/10GH*$2.2 = $440です。

BTCで購入したので、0.0411 BTC を送金しました。
これで1年間、BTC採掘された分からメンテナンス手数料を引いた分が毎日溜まっていきます。
1年間で0.0411を上回ってくれないと赤字です。

メンテ手数料は0.0035$ / 10 GHs / 24h
となっているので、2TH/sの場合は、
0.0035$ * 2000GH / 10GH = $0.7
一日あたり、およそ70円です。

初日の結果

初日の結果です。
f:id:pebble8888:20180203111356p:plain:w600

0.00020281 BTC (1BTC=$9,945として約$2.0)がその日に採掘された量、
メンテ手数料がBTC建で、0.00007182 BTC 引かれ、
一日の利益が 0.00013099 BTC
仮にこの採掘量が一年間続いた場合、0.00013099BTC * 365 = 0.0468 BTC となり、
回収率は0.0468/0.0411 = 113.8% となります。
なんというか微妙な結果になりそうです。
赤字でないだけましですが。

ちなみにこの画面右端の利益予測はメンテ手数料が含まれていませんのでご注意下さい。

f:id:pebble8888:20180203111344p:plain:w600

ちょっと不親切やなあと思います。

マイニング時は、仮想通貨取引とは異なり、毎日、利確している状態となるので、
毎日のBTC価格で利益を計算する必要があります。
HashFlareにはマイニングデータをダウンロードする機能はなさそうなので、確定申告時に備えて、
一ヶ月に1回程度は自前帳簿を更新しておかないと、その頃になってヒーヒーいうことになりそうです。

購入は経費に含めることができる

最初の購入費用(私の場合0.0411BTC)は、確定申告時は、経費に含めることができるようです。

再投資機能

HashFlareには入手したBTCをさらにハッシュレート購入に充てる機能があり、
回収速度を上げることができるようですが、帳簿付けがさらに面倒になるので、 面倒なことが嫌いな私はやりません。

SHA256以外のマイニング

SHA256(BTC)以外に、SCRYPT(LTC)、ETHASH(ETHEREUM)、EQUIHASH(ZCASH)、X11(DASH)のマイニングもできるようですが、
どのくらいの回収率かは不明です。

まとめ

私にとっては帳簿付けがメンドくさすぎるので、これは向いてないなあと思いました。

クラウドマイニングに高額をつぎ込むのはリスクが高い投資です。
失っても問題ない余剰資金でやりましょう。

Monacoin を MacBook Pro で CPU マイニングできるか試してみた

この記事は2018-1-28時点のものです。備忘録として手順を残しておきます。
マシン: MacBook Pro 2017

モナコインのウォレットをダウンロード

Monacoin project

ここからmacOSX版のウォレットをダウンロードします。
立ち上げると全トランザクションのダウンロードが始まります。
10GB程度の空きディスクが必要となるようです。
ダウンロードは2時間ほどかかりました。
BTCに比べたら大分短いです。
ダウンロード途中でも受け取り用アドレスは表示できます。

f:id:pebble8888:20180128133755p:plain

マイニングプールの登録

vippoolにアカウントを作成します。
VIP Pool - Monacoin採掘所 - Home

アドレスの部分はウォレットの受け取り用アドレスを設定します。
登録すると登録したメールアドレスに確認メールが来るので、リンクをクリックしたらアカウント登録完了です。

VIP Pool内のメニュー 「アカウント」-「ワーカー」からワーカーを作成します。

指定difficulty は0.25にしておきました。

マイニングプログラムのビルド

こいつをgit cloneします。

GitHub - tpruvot/cpuminer-multi: crypto cpuminer (linux + windows)

$ ./autogen.sh
$ ./nomacro.pl
$ ./configure --with-crypto --with-curl
$ make

モジュールが足りないと言われる場合は、brew でインストールしたらよいです。
makeが終わり、cpuminer というバイナリが作成されたら成功です。

monacoin.jsonの作成

{
    "api-bind": "127.0.0.1:4048",
    "url": "stratum+tcp://stratum1.vippool.net:8888",
    "user": "ユーザー名.ワーカー名",
    "pass": "パスワード",
    "algo": "lyra2rev2",
    "threads": 0,
    "cpu-priority": 0,
    "cpu-affinity": -1,
    "benchmark": false,
    "debug": false,
    "protocol": false,
    "quiet": false
}

マイニングプログラムの実行

$ ./cpuminer --config monacoin.json 

f:id:pebble8888:20180128135642p:plain:w600

yesという文言が出たら成功のようです。

CPU4つ分で 76kH/s * 4 = 300 kH/s くらい出ています。

利益予測

現時点でのmonacoin ブロック発見者には25 MONA (17,750円)が与えられますが、
私の場合、0.002 MONA/day となっていますので、
1ヶ月回したとしても、0.002 MONA/day * 30 day * 700 YEN/MONA = 42円 となります。
どう考えても電気代の方が上回りそうです。
しかもこんなんでMacBookProが壊れたら泣きます。
マイニングで収益を上げたければ少なくともグラボ導入は必須かもしれません。

f:id:pebble8888:20180128142719p:plain

参考URL

Mac OS XでモナーコインをCPUマイニングする - Qiita

Crypto Currency(仮想通貨) リスト

Crypto Currencyの公開されているソースリポジトリと実装言語をまとめてみました。(2017年12月)
ついでに、githubで管理されているものはissueの数を数えて見ました。
ご指摘ありましたら教えていただけると助かります。

Bitcoin(BTC or XBT)

承認時間: 10 分
Language:C++
Digital Signature: secp256k1
Issue count: 3,604
Consensus: Proof of work (sha256)
github.com

Ethereum(ETH)

スマートコントラクト
Language:Go, C++
Digital Signature: secp256k1
Issue count: 2840
Consensus: Proof of work (将来的にProof of stakeに移行予定)
github.com

Bitcoin Cash(BCH)

Bitcoin Cashは特殊で複数のプロジェクトで独立にノードが実装されています。
ビットコインのハードフォーク(2017年8月)

Language: C++
Digital Signature: secp256k1
Consensus: Proof of work

www.bitcoincash.org

Issue count: 103
github.com

Issue count: 161
github.com

Issue count: 88 https://github.com/bitcoinxt/bitcoinxt

Issue count: 128 github.com

github.com

Monero(XMR)

匿名通貨
Language: C++
Digital Signature: curve25519,ed25519
Issue count: 954
Consensus: Proof of work
github.com

Ripple(XRP)

取引時間 数秒
Language: C++
Digital Signature: Ed25519, secp256k1
Consensus: Proof of consensus
issue count: 314
github.com

Zcash(ZEC)

匿名通貨
Language: C++
Digital Signature: secp256k1
Issue count: 1983
github.com

Lisk(LISK)

Language: JavaScript Issue count: 743
Consensus: Proof of stake
github.com

Dash(DASH)

ビットコインベース
匿名性
取引時間 4秒
Language: C++
Digital Signature: secp256k1
Issue count: 286
Consensus: Proof of work
github.com

Litecoin(LTC)

承認時間2.5min 2011年10月 BTCのハードフォーク
Language: C++
Digital Signature: secp256k1 (scrypt)
Issue count: 224
github.com litecoin.org

VERGE(XVG)

匿名通貨 Language: C
Digital Signature: curve25519, ed25519 (tor project)
Issue count: 226
Consensus: Proof of work
github.com https://vergecurrency.com/langs/ja/

Augur(REP)

Issue count: 133
github.com

NEM(XEM)

Language: Java
Digital Signature: Ed25519, secp256k1
Issue count: 12
Consensus: Proof of Importance
github.com

Monacoin(MONA)

Language: C++
Digital Signature: secp256k1
Issue count: 17
Consensus: Proof of work
github.com

Factom(FCT)

Language: Go
Issue count: 28 github.com

Ethereum Classic(ETC)

イーサリウムのハードフォーク
github.com

EOS

手数料 無料
スマートコントラクト
仮想通貨ではない
eos.io

GNO

Gnosis
gnosis.pm

ICN

ICONOMI
ICONOMI

MLN

Melonport
melonport.com

REP

Augur
augur.net

USDT

Tether
https://tether.to

XDG

Dogecoin

XLM

stellar
www.stellar.org

TRX

Tron
波场[TRON]

BCG

Bitcoin Gold
bitcoingold.org

BCD

Bitcoin Diamond
www.btcd.io

OMG

OmiseGO
Consensus: Proof of stake
omisego.network

ZNY

BitZeny bitzeny.org

secp256k1における体演算の最適化

secp256k1の体演算の最適化手法として、x,yが法素数q未満であることと256bit値の範囲内であることを用いて、
256bitサイズの値を9個の26bit値と1つの22bitの値(9*26+22=256bit)に分割する手法があります。
素数q=0x FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F

q未満の値のマスク値をビット表現すると、上位から
1111_1111_1111_1111_1111_1111_1111_1111 = 0x FFFFFFFF
1111_1111_1111_1111_1111_1111_1111_1111 = 0x FFFFFFFF
1111_1111_1111_1111_1111_1111_1111_1111 = 0x FFFFFFFF
1111_1111_1111_1111_1111_1111_1111_1111 = 0x FFFFFFFF
1111_1111_1111_1111_1111_1111_1111_1111 = 0x FFFFFFFF
1111_1111_1111_1111_1111_1111_1111_1111 = 0x FFFFFFFF
1111_1111_1111_1111_1111_1111_1111_1110 = 0x FFFFFFFE
1111_1111_1111_1111_1111_1100_0010_1111 = 0x FFFFFC2F
となり下位から26bitずつにわけ10個目を22ビットとします。
11_1111_1111_1111_1111_1111 = 0x 3FFFFF
11_1111_1111_1111_1111_1111_1111 = 0x 3FFFFFF
11_1111_1111_1111_1111_1111_1111 = 0x 3FFFFFF
11_1111_1111_1111_1111_1111_1111 = 0x 3FFFFFF
11_1111_1111_1111_1111_1111_1111 = 0x 3FFFFFF
11_1111_1111_1111_1111_1111_1111 = 0x 3FFFFFF
11_1111_1111_1111_1111_1111_1111 = 0x 3FFFFFF
11_1111_1111_1111_1111_1111_1111 = 0x 3FFFFFF
11_1111_1111_1111_1111_1011_1111 = 0x 3FFFFBF
11_1111_1111_1111_1100_0010_1111 = 0x 3FFFC2F

26ビットの値は変数としてuint32_tを使い、32ビットの値の範囲内の演算であれば、そのまま計算できます。
元は法素数倍してもmod qの世界では同一値ですから、10個の要素に同時に、これらのマスク値の倍数を加えても、
値としては同じということになります。

なお、32bitの要素を8個使って(32*8=256bit)表現するものも使います。