BIP 34 ビットコインブロックのバージョンアップ(aka. softfork, v1 → v2)

Segwit なかなか有効化されないなあ…ところでビットコインのバージョンアップはどのように行われるのだろう?と疑問に思ったので BIP を眺めてきました。BIP とは Bitcoin Improvement Proposal の略で、ビットコインの改善提案ですかね、がまとめられているものです。GitHub で公開されています。

github.com

Segwit は BIP 9 の手順でデプロイされるようですが、BIP 9 から BIP 34 への参照があったので先に BIP 34 を見てみました。

BIP 34 は

Block v2, Height in Coinbase

ということで、バージョン1からバージョン2へバージョンアップする際の手順を示した BIP です。バージョン2では scriptSig という場所の最初に coinbase の height を入れることにしたようです。 BIP 34 には実際の実装を行った pull request へのリンクも貼られています。コードを見ると理解が深まります。良い。

各ブロックにバージョンが埋め込まれており、マイナーの間にどれくらいバージョン2以降が浸透しているか(過去nブロックにおけるバージョンを確認する)によって挙動を変えています。

  • バージョンアップ率 75%以上: 過去1000ブロック中、750ブロック以上がバージョン2以降である
    • バージョン2以降であり、scriptSig の最初に height を持っていないブロックは捨てる
  • バージョンアップ率 95%以上: 過去1000ブロック中、950ブロック以上がバージョン2以降である
    • バージョン1のブロックは拒否する

さて Decentralize で皆が好き勝手にやっているビットコインネットワークでバージョンアップが成功するのでしょうか?ブロックのバージョンはブロックヘッダの最初の4バイトです。ブロックヘッダを書くのはマイナーなので、マイナーがバージョンアップするか、バージョンアップするモチベーションがあるかが焦点になります。

旧バージョンでのブロック受け入れ判定のコードを見ると、ブロックのバージョンによって拒否はしていないようです。 従ってバージョンアップ率ごとのブロック受け入れ状態は次のようになります。

  • 0% ~ 75%
    • 旧バージョン利用マイナー: ブロックは受け入れられる
    • 新バージョン利用マイナー: ブロックは受け入れられる
  • 75% ~ 95%
    • 旧バージョン利用マイナー: ブロックは受け入れられる
    • 新バージョン利用マイナー: ブロックは受け入れられる
  • 95% ~ 100%
    • 旧バージョン利用マイナー: ブロックは受け入れられない
    • 新バージョン利用マイナー: ブロックは受け入れられる

旧バージョン利用マイナーはブロックが受け入れられない可能性が出てきます。 せっかく計算資源を消費してマイニングしたブロックが受け入れられないとマイナーとしては何をしているかわかりません。バージョンアップするモチベーションはありそうです。

ところでバージョンアップ率が95%のとき、古いバージョンを動かしている5%のノードではバージョン1のブロックを受け入れ、その他大勢は受け入れないことになります。これは問題にならないのでしょうか? 一時的にはバージョン1のブロックが先頭に付いた状態のチェーンを5%のノードが採用する状態が出来ますが、マイニングパワーの95%が新しいバージョンとなっているので、すぐにバージョン1のブロックを含まないチェーンの方が長くなります。 ビットコインでは最長のチェーンを採用することになっているので、バージョン1のブロックを含むチェーンは採用されません。

今回は BIP 34 を見ましたが、BIP 9 もそのうち読みたい。どうやら複数の機能が並行で試せるようになっているみたい(?)

bitcoin アドレスで使われている base58 encoding

Bitcoin ではアドレスや秘密鍵の文字列表現に base58 encoding を使います。

Base58 - Wikipedia, the free encyclopedia

base64 は良く見かけますが、base58 は bitcoin で初めて見ました。

base64a-z, A-Z, 0-9, +/ の 64文字でエンコーディングします。 base62 は base64 の文字から +/ の2文字を除いた 62文字でエンコーディングします。 base58 は base62 の文字から、0 ゼロ、O 大文字o、I 大文字i、l 小文字L の6文字を除いた 58文字でエンコーディングします。

除く理由は読みづらいから。 0Oo (ゼロ、大文字o、小文字o), Il1 (大文字i、小文字L、数字1)あたりはフォントによっては見間違えやすいです。

紙に印刷した秘密鍵を読み取るときに間違えて悲しい思いをしないように、というサトシの心遣いでしょうか。

なお、58文字の並べ方にいろいろあるらしく、「base58 で」と言っただけでは一意にエンコーディングが定まらないらしい。

  • Bitcoin アドレス: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
  • Ripple アドレス: rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz
  • Flickr の URL に使われているやつ: 123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ

BitcoinFlickr のやつは自然にみえますが、Ripple のやつは一見おかしな感じですね。 ランダムなようにも見えますが、よく見ると JKLM PQRST VWXYZ などアルファベット順で連続した文字列も見えます。 いったいどういう順番になっているのでしょう?

Bitcoin と Ripple は暗号通貨ですが、Flickr の URL にも使われているのですねえ。 Flickr の解説 blog が 2009年4月13日にかかれており、bitcoin の論文が2008年10月31日なので、半年くらい Flickr のほうが遅いですか。 当時 bitcoin はまだまだ知名度が低かったのではないかと思いますが、Flickr の人たちは bitcoin を参考にして採用したのでしょうか?

bitcoin 接続事始め

前回は bitcoin で通信を始める時のピアを得る方法を学びました。

kawachi.hatenablog.com

今回は通信してみたいと思います。

接続するとまず最初に version 番号を交換することになっているようです。 人に出会ったらまず挨拶をしましょうということですね。

今回は、DNS から得た seed peer に接続して、version メッセージを送って、version メッセージを受け取ってみます。

バイナリフォーマットのメッセージですが、scodec という便利ライブラリの bitcoin ようメッセージを定義している bitcoin-scodec というのがあったので、使ってみました。

github.com

適当に書いたコードがこれです。

github.com

受け取った version を最後に集計してみました。 DNS で返される peer の seed node 群は代表的な bitcoin プログラムが動作していると予想されます。

gist1a241b14b083c087400d

Satoshi というのが githubbitcoin/bitcoin ぽいですね。 ここで設定されているのが見えます。

bitcoin/clientversion.cpp at ad57b310bac44a7e470cf66276421f2bbc61b1f0 · bitcoin/bitcoin · GitHub

version は 0.9.1 から 0.11.99 までレポートされていますが、大半が Satoshi でした。

Bitcoin XT というのはこれのことかな。

bitcoinxt.software

Bitcoin XT is an implementation of a Bitcoin full node that embraces Bitcoin's original vision of simple, reliable, low-cost transactions for everyone in the world. It is based upon the source code of Bitcoin Core, and is built by taking the latest stable Core release, applying a series of patches, and then doing deterministic builds so anyone can check the downloads correspond to the source code.

あとは /Satoshi:0.11.1/ljr:20150921/ というのも見えます。 Bitcoin LJR のことですかね。

Bitcoin LJR is a fork of Bitcoin Core (since 2011 December) with a collection of improvements maintained out of the master git tree. It comes in a "functional" flavour with only improvements to the software itself, and a "combined" flavour which also includes enhancements to relay and mining policy code.

peer から順にたどっていけば他のノードにアクセスできるので、全ノードのシェアもある程度簡単に集計できそうですね。

Bitcoin P2P 通信の seed

金曜日ですね。ビールが美味しいです。

Bitcoin で通信してみたいと思って bitcoin wiki を眺めていました。

BitcoinP2P で動作します。 Client-server のように決まったホストがないので、どこにつなげばいいかはどうやれば分かるでしょうか?

Network - Bitcoin Wiki に書いてありました。

3 つあるので順番に見ていきましょう。

Addr

ひとつめは固定の IP アドレスリスト。 これらの IP アドレスには bitcoin が動作するノードが居るので信じてつないでくださいね、というやつ。

bitcoin レポジトリの nodes_main.txt にかかれているのがこれでしょう。 先頭のほうをみると次のような行が確認できます。

1.34.168.128:8333
1.202.128.218:8333
2.30.0.210:8333
5.9.96.203:8333
5.45.71.130:8333

DNS

ふたつめは DNS

IP アドレスリストと同じく、このリストを信じてね。というやつですね。 bitcoin レポジトリの chainparams.cpp に書かれているのがこれぽいですね。 6つのドメインが書かれています。

  • seed.bitcoin.sipa.be
  • dnsseed.bluematt.me
  • dnsseed.bitcoin.dashjr.org
  • seed.bitcoinstats.com
  • bitseed.xf2.org
  • seed.bitcoin.jonasschnelli.ch

ソースの方には各行の後ろにコメントで人の名前がかかれています。 bitcoin 界で信頼の置ける御仁だったりするのだろうか?知らないけど。

DNS 問い合わせると IP アドレス一覧が返ってきます。 返ってくる IP アドレスの port 8333 で動いていると仮定していいんでしょうか。

試しに問い合わせてみるとこんな感じでズラーっと返ってきます。

$ dig +short dnsseed.bluematt.me
24.130.44.69
5.196.82.16
221.146.232.87
198.71.92.235
195.154.15.146
(以下続く)

他の 5つはそれぞれいくつか IP アドレスが返ってきたんですが、 seed.bitcoin.sipa.be はひとつもアドレスが返ってきませんねえ。 Pieter Wuille さん頑張って。とか言っとけばいいのだろうか?

IRC

3つめは IRC。えっ IRC

irc.lfnet.org の #bitcoin00 から #bitcoin99 までのルームのうち、ランダムなルームに join します。 nick は IP アドレスをエンコードしたものにします。 チャネルに参加している nick 一覧を得て、decode すれば bitcoin の seed が得られるって寸法です。

IRC使うのかー。洒落てるな(?)と思いましたが、この方法はバージョン 0.6.x 以降ではデフォルトでオフられているようです。

以上、最初の接続先を得る方法3つを学習しました。

Bitcoin アドレスの残高を調べる

kawachi.hatenablog.com

というわけでビットコインのアドレスは使い回すは一般的には良くないが、寄付などでは良いのではないかと書いたが、寄付の受付をアドレス使い回しでやると良いといっている記事があった。

genxnotes.com

ブロックチェーンは公開された帳簿なので、誰でも全ての取引を照会することができます。したがって、寄付金を募っているウォレットにはいくら集まったのか、またどのような資金の使われ方がされているのかが一目瞭然なのです。

全取引が一目瞭然ということは悪質な詐欺を極限まで減らすことができるということです。

blockchain を全部舐めれば、どのアドレスにいくらの残高があるとか、どのアドレスに対して支払いを行ったかとかがわかるはずですね。

Blocktrail という会社が運営している Block explorer というサービスでは、(おそらく)アドレスごとに取引の内容をデータベース化しており、アドレスの残高を眺めたりすることができます。

BLOCKTRAIL | Bitcoin API and Block Explorer

たとえば この記事 で寄付受付用に公開されているアドレスがあります。

Anyway, if you like to donate for one of my projects or this article, feel to send bitcoins to 15B8b5yCB5sK7hSwbhyQQZpHrRYzvmxrAA ;-).

このアドレスの残高を見てみましょう

f:id:tkawachi:20151119234820p:plain

これまでに6回の取引が行われ、0.71068296 BTC の残高があることがわかります。

Apache財団 のアドレスは少しずつですが寄付が集まってますね

このように寄付に単一の bitcoin address を使えば「みなさまの寄付により〜円集まりました」とかいちいち集計しなくても誰でもわかって便利です。

一方で Mozilla財団Wikipedia では寄付の受付に coinbase というサービスを利用しており、一定時間ごとに違うアドレスが使われているようです。

まだまだ知らないことが多いので同じアドレスで寄付を受け付けることによるデメリットもあるのかもしれませんが、同じアドレスで受け付けたほうが透明性の点からは評価できますね。

Bitcoin のアドレスは毎回変えよう

photo by zcopley

この先 bitcoin を扱うためのリテラシの必要性が高まるのではないかと感じている今日このごろです。 自分の子ども世代では国の発行する通貨に追加してデジタル通貨も扱えなきゃいけないんだろうなあ、大変だなあ。

というわけで bitcoin について調べているのですが、 Bitcoin に送金する際に使われるアドレスは毎回変えたほうが良い、と Address reuse - Bitcoin Wiki に書いてありました。 アドレスの使い回しはできるけどやらないほうがいい、ってことですね。 Bitcoin beginner の私は知りませんでした。

同じアドレス(以下、アドレスAと呼びます)をずっと使っていた場合、個人と結び付けられた時に厄介なことになります。 Bitcoin では取引内容、すなわちアドレスXからアドレスYへいくら移動したという情報が全て公開されています。 すなわち、アドレスAの残高も丸見えなわけです。

私が通販で買い物をして、アドレスAから送金して、自分の住所へ何かを届けてもらったとします。 そうすると、通販の運営者は、私という個人とその住所、アドレスAを関連付けることができます。 もし私がアドレスAをずっと使いまわしており、全貯蓄の100億円相当*1をアドレスAに入れていたとしたらどうなるでしょう。 通販の運営者には、私がどこに住んでおり全貯蓄がいくらあるか分かることになります。 悪意のある人にこの情報が渡ると、恐喝の対象になったり、何かの際に足元を見られたりするわけです。 あまり気持ちの良いものではないです。

ではどうするかというと、一度取引に使ったアドレスはもう使わないというのが正しい運用になります。 そうすると bitcoin の受け取り毎に別のアドレスを使うことになります。 アドレスが増えて面倒になりそうですが、複数のアドレスをまとめて扱える wallet というものを使うのが普通みたいですね。

逆に残高がわかってもいい状況、たとえば募金を募る場合などではひとつのアドレスでいいのかもしれません。

参考 genxnotes.com

*1:もちろんそんなに持ってませんよ…

Android でプログラムを書いて遊ぼう

常日頃、非生産的な通勤時間をどうやって過ごそうかと思いを巡らせています。 大体、Android 端末(Nexus 5)で Pocket に溜めた記事を読んだり、 Kindle で本を読んだり、podcast を聞いたりで時間を潰してるんですけどね。

昨日、 root を取っていない Android で動く Debian が Play store にあるのを見つけました。

f:id:tkawachi:20151116012222p:plain

GNURoot Debian - Google Play の Android アプリ

インストールしてみましたが、普通に apt-get とか動くのはなんだか新鮮です。 /home の下のファイルはなぜか実行権が付けられない?とか、プログラムによっては動かなかったりしますが、C も javaghcHello world は動きましたし、それなりに遊べそうな雰囲気はあります。*1

キーボードは打ちにくいものの、vim も動きました。

Kindle で入門本を読みながら、GNURoot で動作確認するなんてのもなかなか楽しいかな、と思いました。

*1:go の Hello world はなぜか segmentation fault した。