読者です 読者をやめる 読者になる 読者になる

Tech と Culture

テクノロジーとカルチャー

翻訳:Satoshi Client Transaction交換

次はこれ。

Satoshi Client Transaction Exchange - Bitcoin Wiki

分からない部分あり。

Satoshi Client Transaction交換

1 概要 2 walletの送信 3 定期的なアドバタイズメント 4 リレー 5 他の参照 6 脚注

1 概要 Satoshiクライアントはローカルで生成されたトランザクションをアドバタイズし、他のノードからのトランザクションをリレーします。この記事はトランザクションの交換を取り扱う操作について説明します。 トランザクション交換は、トランザクションが標準で有効の場合のみ行われます。

2 walletの送信 クライアントは定期的にmain.cppのSendMessages()を呼び出します。それはResendWalletTransactionsを呼び出し、ローカルに生成されたトランザクションを送信します。 このルーチンは前回から新しいブロックがあるか確認し、もし存在しているならローカルのトランザクションがまだブロックに入ってないか確認し、トランザクションを全てのノードに送信します。これは30分毎に行われます。 トランザクションは最後の受信したブロックより少なくとも5分以上古い場合再ブロードキャストされます。ソートされ古いものから順に送られます。

3 定期的なアドバタイズメント クライアントは定期的にmain.cppのSendMessages()を呼び出します。そこではメッセージがリモートのノードに送られるべきか決定します。それぞれのメッセージの処理の繰り返しにおいて、一つのノードが”trickle node”として選ばれます。このノードは適切であれば”addr"メッセージ受信する唯一つのノードとなります。 inventoryのセクションでは、クライアントはtrickleノードでなければランダムに決められた1/4のトランザクションのinventoryを送信します。この場合、全てのトランザクションを受信します。 ???????

4 リレー クライアントがトランザクションを”tx”メッセージで受け取った時、RelayMessageを呼び出し、それがRelayInventoryを呼び出して、他の全てのノードに送るinventoryをキューにいれます。

5 他の参照 transation broadcasting

翻訳:Satoshiクライアントのノード接続性

次はこれ。

Satoshi Client Node Connectivity - Bitcoin Wiki

同じく適当。

 

Satoshiクライアントのノード接続性
 
1 概要
2 接続ルール
 2.1 外向きのスタティックアドレス
 2.2 外向きの制限
 2.3 シードノード
 2.4 外向きのランダムな選択
 2.5 内向きの受け入れと切断
 
1 概要
Satoshiビットコインクライアントは他のノードとの接続生成をマネージメントするスレッドをつくります。net.cppの中のThreadOpenConnections2と呼ばれる関数の中にそのスレッドのコードがあります。
クライアントはnet.cppの中にある、ThreadSocketHandler2と呼ばれるスレッドで、新しい内向きのコネクションと切断を適切なタイミングでハンドルします。
コネクションを生成するスレッドは他のノードのアドレス発見は行いません。
その情報は様々な方法で集められます(Node Discoveryの記事を参照)
コネクションスレッドは有効なアドレスの中からアドレスを選択し、適切なタイミングでコネクションを生成したり切断したりします。これが全てです。
ノードアドレスは以下のようなルール群に従って選ばれます。
 
2 接続ルール
2.1外向きのスタティックアドレス
 -connect引数でユーザがアドレスを指定した場合、ノードはそのアドレスだけを使います。それぞれのノードに対してコネクションを成立させようとしたのち0.5秒スリープします。それからシャットダウンまでループを繰り返します。コードはOpenNetworkConnection(addr)をコールすることによってコネクションを成立させます。すでにコネクションがオープンしている場合、OpenNetworkConnectionは何もしません。
 
もしユーザーが -node引数によってアドレスを指定した場合、スタートアップ時は(それぞれ0.5秒の遅延をもって)これらのノードに対してコネクションを作ります。これらのコネクションが試された後、コードは標準的なコネクションをハンドルするコードを処理します。
 
2.2外向きの制限
コネクションをハンドリングするコードはシャットダウンまで様々な関数を実行する一つのループです。ループが最初に行うことは外向きの接続の数を数えることです。次に(8または、-maxconnectionで与えられた数)に到達していたら、数がmax以下になるまで2秒の遅延ループに入ります。
コネクションの数が制限以下である場合、ノードは他のノードに接続をこころみます。次の説を参照してください。
 
2.3 シードノード
もしノードが他のアドレスを得ることができなかった場合、おそらくこれらの方法が失敗しているのだが、ノードはソフトウェアにハードコードされている320のアドレスのリストを使用します。
可能な場合、シードノードを取り除くコードが存在しています。おそらくこれはシードノードへの過負荷を避けるためです。一度ローカルノードが十分な数のアドレスを得たら(おそらくシードノードから得た)、コネクションスレッドはシードノードのコネクションをクローズします。
 
2.4 外向きのランダムな選択
最初にコードはアドレスをa.b.c.*バケット(?)に    一つのコネクションのみがそれぞれの24bitのnetmaskされたネットワークを作ります。
次に全てのアドレスに対してループし、”ready”状態かどうか決定します。そして、複雑な計算式でそれぞれのアドレスに対してスコアを計算します。もっとも高いスコアを持つアドレスが勝利し、OpenNetworkConnectionが呼び出されます。そして、コードはスレッドのメインのループを完了し、繰り返します。
readinessを決定するために、コードはIPと他のエントロピーをハッシュし、1〜3600の乱数を決定します。もしアドレスが標準でないポートを指定していた場合、2時間のペナルティが与えられます。これはリトライ間隔を調整するための数字です。
メインのリトライ間隔は基本的に最後につながった時間の平方根に前パラグラフの乱数調整値を足したものです。しかしながら、もしノードが最後につながったのが一時間以内の場合は、リトライ間隔は10分となります。以下のテーブルがコードの中にあります。
// Last seen  Base retry frequency
//   <1 hour   10 min
//    1 hour    1 hour
//    4 hours   2 hours
//   24 hours   5 hours
//   48 hours   7 hours
//    7 days   13 hours
//   30 days   27 hours
//   90 days   46 hours
//  365 days   93 hours
 
インターバル計算の後、もしアドレスがすでにインターバル内にコンタクトされていれば(?)アドレスはスキップされます。
もしアドレスが一日以上古ければ、それをスキップします。もしIRCアドレスを取得でき、ノード接続ができれば、もしそれが本当にアクティブであれば、アドレスのアドバタイズを見ることができるという仮定のもとにそれをスキップします。
最後にリトライの準備ができていると思われる全てのアドレスに対して、最大24時間で最も長い間コンタクトできていないアドレスが選ばれます。しかしながらそこには少しひねりがあります。スコアの計算式は以下です。
 
int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
 
アドレスは最後に見られたのちに毎秒ペナルティがあります(そして乱数による調整も)
 
2.5 内向きの受け入れと切断
クライアントはnet.cppにある、ThreadSocketHanler2と呼ばれるスレッドの中で適切なタイミングで内向きの接続と切断をハンドリングします。
ソケットスレッドは、単純なループで、fDisconnectフラグが立っている(そしてバッファが空である)ソケットを切断し、全てのソケットに”select”の準備をし、”select”をコールします。”select”はシステムコールで、ソケットのアクティビティを待ちます。
そのコールが帰ってきたとき、ノードはいかなる新しいコネクションも受け入れ、ready状態のいかなるソケットの送受信を行い、アクティブでないいかなるソケットもfDisconnectフラグを立てて切断します。
ソケットは、もし60秒間の過去のもので、データが送受信されていない場合切断されます。
ソケットは過去90分に渡ってデータの送受信が過去90分間データの送受信がない場合切断されます。
ソケットは現在の内向きのデータがバッファリミットを超えていたら切断します。
(net.cppの中で if (nPos > ReceiveBufferSize())を検索)
ソケットは現在の外向きのデータがバッファリミットを超えていたら切断されます。
(net.cppの中で if (vSend.size() > SendBufferSize()) を検索)
 

翻訳:Satoshiクライアントの初期化とスタートアップ

続けてこちら。
 
Satoshiクライアントの初期化とスタートアップ
 
1 スタートアッププロセス
2  fClientモード
3  net.cppのStartNode()スレッド
4  net.cppのIRCSeedスレッド
5  net.cppのThreadSocketHandlerスレッド
6  net.cppのThreadOpenConnectionsスレッド
7  net.cppのThreadMessageHandlerスレッド
8  rpc.cppのThreadRPCServerスレッド
 
1 スタートアッププロセス
クライアントはスタートアップ時に一定の数のスレッドを作ります。アクティブなネットワークソケットの全ての読み、書きは一つのスレッドによってハンドルされます。
プログラム中のmain()のエントリポイントはinit.cppにあります。main.cppの中にmain()を探さないようにーその中には見つかりません。
main()が最初に行う事はAppInitをコールすることで、それはAppInit2をコールします。AppInit2はどのようにアプリケーションがエラーをハンドルするかに関する、たくさんの初期化の仕事をします。あるポイントでAppInit2はParseParametersをコールし、基本的な引数の幾つかがハンドリングされます。
さあ、GUIウィンドウがすでに存在しているかチェックし、もし存在していればフォアグラウンドに持ってきます。
次にbitcoinディレクトリのlock fileを生成し、もしすでにbitcoinが実行中であればメッセージを出力してイグジットします。
次にbitcoinのポートをリッスンします。もしポートがすでに使われていたり、他のエラーがあればメッセージを出力してイグジットします。
次にデータベースからIPアドレスをロードし、ブロックインデックスをロードし、それからウォレットをロードします。
次にウォレットからトップのブロックナンバーを取得します。 -rescan引数が指定された時は0になります。
Side Note: printfはutil.hで再定義されています。なのでprintfは実際にはOutputDebugStringFであり、それはもし適切であればファイルへ出力されます(util.hとutil.cppを参照)。“loop”はutil.hでfor(;;)と定義されています。
次に、もう少し初期化処理を行い、パラメータを処理し、最後にGUIのメインウィンドウを開きます。
次に、二つのスレッドを作ります。
  1. StartNode()
  2. サーバーとして動作する場合:ThreadRPCServer()
ここがこれらのスレッドが生成される唯一の場所です。
StartNode()はnet.cppの中にあり、ThreadRPCServer()はrpc.cppの中にあります。
最後に、GUIとしてコンパイルされていなかったら、五秒間のスリープの後、無限ループに入ります。
 
2 fClient Mode
クライアントには、ブロックヘッダーのみをダウンロードするモードを許すコードが存在していることは注目に値する。この実装はlightweightクライアントで使われることを意図しており、そこでは全てのブロックとtransactionを検証やストアする必要がない。これはfClient変数でコントロールでき、現在はfalseにハードコードされている。これは現在はまだコードが完成しているとは想定されていないということです。このモードはfClientモードと知られており、Simplified Payment Verification(SPV)モードという言葉もlightweightクライアントを表現するのに使われています。
 
3 net.cppのStartNode()スレッド
StartNodeはネットワーキングスレッドの一種のマスターのようなものだ。
最初にCNodeを作り、コミュニケーションを取り扱うためにlocalhost 127.0.0.1を内部アドレスとする。
次にローカルのIPアドレスを取得する。Windowsではlocal host nameを使用して見つける。Linuxでは、loopbackインターフェースでない、upされているインターフェースを見つけて最初のIPアドレスとします。
次にThreadGetMyExternalIPスレッドをつくり、ローカルIPアドレスサードパーティの検証を使用して確認します。もしproxyを使用していても、接続しようとしてくるコネクションは無視するので問題ありません。
次に、もしuPnPが使用されている場合は、ThreadMapPortが作られてポートマッピングを行います。
次にThreadIRCSeedスレッドが作られてIPアドレスを交換します。
次にThreadSocketHandlerスレッドが作られて、ソケットで送信、受信を行い、コネクションを受け付けます。
次にThreadOpenConnectionsスレッドによって外向きのコネクションを初期化します。
次にThreadMessageHandlerスレッドをつくり、メッセージを処理します。
最後にもし指定していたなら、マイニングスレッドが始まります。
 
4 net.cppのIRCSeedスレッド
92.243.23.21のポート6667に接続し、チャンネルにジョインし、それからラインを読み、他のユーザを検索します。
 
5 net.cppのThreadSocketHandlerスレッド
必要なサービスを行うサービスソケットの無限ループに入ります。接続が切れたノードをハンドルします。”選択”デスクリプタリストを準備し、”選択”ヲコールシ、カンケイする全てのソケットを50msecのタイムアウトでI/O待ちします。リスニングソケット上の新しい、接続してくるコネクションを処理します。それらにCNodeを作ります。受信と送信をハンドルします。何もしないソケットをディスコネクテッド状態にします。
 
6 net.cppのThreadOpenConnectionsスレッド
パラメータ、シード、IRC等からノードを解決し、ループに入って一つづつ接続していきます。
 
7 net.cppのThreadMessageHandlerスレッド
このスレッドは全てのノードをとおして、main.cppのProcessMessages(pnode)をコールします。そこではノード受信キュー(pFrom->vRecv)に有効なメッセージを探し、もし見つかった場合は、main.cppのProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
をコールします。
それからスレッドはそれぞれのノードに対しmain.cppのSendMessagesをコールシ、それぞれのノードに対する適切なメッセージを作って送信します。
 
8 rpc.cpp内のThradRPCServerスレッド
このスレッドは少し込み入っていて、HTTP(S)+JSONRPCサーバーをboostクラスで実装しています。おそらく大半の開発者にとってはあまり馴染みのないものです。
以下のような行を見ることができます。
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
 
また以下のような行もあります。
boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
if(!api_caller.timed_join(boost::posix_time::seconds(GetArg(“-rpctimeout”,30))))
 
上記のコードは30秒タイムアウトをHTTPrequestを読むときに設定するためのスレッドを作ることが見て取れます。HTTPリクエストが読まれたとき、パースされ、リクエストコマンド名に対応するルーチンが呼ばれてリクエストがハンドルされます。これはシャットダウンされるまでループします。

翻訳: Network

続けてこっちも。

同じく適当なので自己責任で。

 

Network - Bitcoin Wiki

Network
 
Bitcoinトランザクションとブロックを伝達するために単純なブロードキャストネットワークを使用します。全てのコミュニケーションはTCP上で行われます。Bitcoinはポートパラメーターによって、8333以外の全てのポートを使用可能です。IpV6は Bitcoind/Bitcoin-Qt v0.7からサポートされています。
 
1 メッセージ
2 コネクション
3 標準リレー
4 最初のブロックダウンロード
5 SPVクライアント
6 ブートストラッピング
    6.1 Addr
    6.2 DNS
    6.3 IRC
7 ハートビート
8 他の参照
 
1 メッセージ
・version - プログラムのバージョンとブロック数の情報。最初に接続するときに交換される
・verack  - バージョンメッセージの応答として送られ、接続しようとしていることを知らせる
・addr     -  一つ以上のIPアドレスとポートのリスト
・inv        -  “私はこれらのブロック/トランザクションを持っています:…...” 通常は、新しいブロックもしくはトランザクションがリレーされる時のみ送られ雨r。これはリストのみであり、実データは含まれない
・getdata - 一つのブロックもしくはトランザクションのハッシュによるリクエスト
・getblocks - 一定範囲内の全てのブロックのinvのリクエスト
・getheaders - 一定範囲内の全てのブロックヘッダを含むheadersメッセージのリクエスト
・tx        - トランザクションの送信。getdataリクエストに対する応答としてのみ送られる
・headers   -  2000ブロックヘッダーまでの送信。Non-generators ブロック全体の代わりにブロックのヘッダーをダウンロードできる
・getaddr   -  (ブートストラッピングのための)アクティブピアのかたまりを含むaddrメッセージのリクエスト
・submitorder, checkorder, reply IP transactionで使用  ※現在は使用されていない
・aleart  - network alertを送る
ping - 何もしない。コネクションがまだ生きているかのチェックに使われる。コネクションが死んでいる場合、TCPエラーが発生する。
もっと詳細な技術情報はプロトコル仕様を参照のこと。
 
2 コネクション
ピアに接続するためには、自分のバージョン番号とブロック数、現在時刻を含むversionメッセージを送る。リモートのピアは、もしあなたのバージョンをによる接続を受け付ける場合は、verackメッセージを返答し、そしてリモートピア自身のversionメッセージを送ってくる。もしあなたが彼のバージョンからの接続を受け付ける場合は自分のverackメッセージを返す。
あなたの全てのピアからの時刻データは集められ、median値が(versionメッセージ以外の)Bitcoin内で時刻を使用する際に使われます。
その後、”getaddr”と”addr”メッセージを交換し、全ての知らないアドレスをストアします。 “addr”メッセージはしばしば一つのアドレスのみを含みますが、時々1000個以内のアドレスを含みます。これは交換の初期では普通のことです。
 
3 標準リレー
 誰かがトランザクションを送る時、それを含むinvメッセージを全てのピアに送ります。それらのピアはgetdataで完全なtransactionデータを要求します。それを受け取った後、もしtransactionが有効であると考えれば、彼らは彼らの全てのピアにinvメッセージでtransactionをブロードキャストします。それが続いていきます。ピアはtransactionの要求やリレーは、すでにそのtransactionを持っていない場合のみ行います。transactionはしばらくしてブロックに含まれていくとともに忘れられていくのですが、ピアは決してすでに知っているtransacctionを再ブロードキャストしません。ただしtransactionの送付者と受信者は再ブロードキャストを行います。
generatingしている(?)ものは誰でも、受信した正当なtransactinを収集し、それをブロックに含めようと働きます。誰かがブロックを発見した時、上記と同じようにそれを含むinvを全てのピアに送付します。transactionsの時と同じように働きます。
全ての人は24時間毎に、自分のIPアドレスを含む”addr”メッセージをブロードキャストします。ノードはこれらのメッセージを2つのピアにリレーし、もしそれが新しいものであるあるならばストアされます。このシステムを通して、全ての人が、ある瞬間にどのIPアドレスが接続しているかクリアな概要を持つことんいなります。ネットワークに接続したのち、あなたの最初の”addr”メッセージで全ての人のアドレスデータベースにほとんど瞬時に加えられます。
ネットワークalertは”alert”メッセージによってブロードキャストされます。”inv”のようなシステムは使われていません;これらは全てのalertを含んでいます。もし、受信したalertが有効な場合(誰かのprivate keyで署名されています)、全てのピアにリレーされます。alertが有効であるかぎり、全ての新しいコネクションに対して再ブロードキャストされます。
 
4 最初のブロックダウンロード
コネクションの最初に、あなたが知っている最新のブロックのハッシュを含む”getblocks”メッセージを送付します。もしピアがそれが最新ブロックではないと考えた場合、あなたがリストした先の500個のブロックを含む”inv”メッセージを送付します。そこで、あなたはこれら全てのブロックを”getdata”でリクエストします、ピアは”block”メッセージでそれらをあなたに送付します。あなたが、これらのブロック全てをダウンロードして処理したのち、全てのブロックを得るまで、あなたは次の”getblocks”メッセージを送付します。
 
5 SPVクライアント
BIP0037はSimple Payment Verificationによる軽量クライアントを紹介しています。SPVクライアントは残金の存在を検証するのに、完全なブロックの内容をダウンロードする必要がなく、そのかわりにブロックヘッダのチェインをリレーし、他のノードから必要なデータを得るためにbloom filterを設定します。これらのクライアントの方法は、フルノードと非常にセキュリティの高いtrustlessなコミュニケーションを可能にしますが、SPVクライアントが探している情報はどのアドレスなのかをピアが推論することに対して少し高価なプライバシーを必要とします。
MultibitやBitcoin Walletは基礎にbitcoinjライブラリを使用した、このような方法で動くwalletです。
 
6 ブートストラッピング
あなたはどのピアに接続するかを、あなたのアドレスデータベースを最後にアドレスを見た時刻によってソートし、すこしだけランダマイズして選びます。
Bitcoinはピアを見つけるのに3つの方法があります。
 6.1 Addr
上で説明されている“addr”メッセージは、IRCブートストラッピング方法とにたような効果を作り出します。ピアが参加したら必ず、早い時間に知ることができます。ただし、ピアが離脱した時はしばらくの間知ることができません。
Bitcoinは”seed nodes”として知られているアドレスリストからも立ち上げられます。もしあなたが、IRCに接続できず、一度もネットワークにつなげていない場合、クライアントはアドレスデータベースをこのリストのノードの一つにつなぐことによって更新します。
-addnodeコマンドラインオプションをマニュアルでノードを追加することに使用できる。 -connectオプションはbitcoinを特定のノードに接続することを強制する。
6.2 DNS
Bitcoinは幾つかのホスト名のIPアドレスDNSに問い合わせ、これらをアドレスのリストに追加する。これはv0.6x以降のデフォルトのseedingメカニズムである。
6.3 IRC
v0.6xのBitcoinクライアントはIRCブートストラッピングはもはやデフォルトでは有効になっていない。以下の情報は古いバージョンのために記す。
Bitcoinirc.Ifnet.orgの#bitcoin00から#bitcoin99の間のチャンネルにランダムに参加する。あなたのニックネームはあなたのIPアドレスからエンコードされている。チャンネルにいる全てのユーザのニックネームをデコードすることによって現在Bitcoinに接続しているIPアドレスのリストを得ることができる。
ポート6667で外部に接続できないサーバーのため、Ifnetサーバはポート7777でもリッスンしている。
 
7 HeartBeat
クライアントがなんらかのメッセージを発してから、もし30分以上過ぎていれば、ピアノードへのコネクションをキープするためメッセージを送信する。
もし、ピアノードと何らかのメッセージでコミュニケートしてから90分以上過ぎていれば、クライアントはコネクションが閉じたと判断する。
 

翻訳:Satoshiクライアントのノード発見

Bitcoindのノード発見の部分を勉強したいと思ったので、以下のページを翻訳してみた。少し情報が古いような気がするけど、各自自己責任でお願いします。
Satoshiクライアントのノード発見
 
1 概要
2 "getaddr"メッセージの取り扱い
3 発見方法
  3.1 ローカルクライアントの外部アドレス
  3.2 コールバックアドレスへの接続
  3.3 IRC アドレス
  3.4 DNS アドレス
  3.5 ハードコードされた "seed""アドレス
  3.6 "addr"アドバタイズメント
       3.6.1  アドレスリレー
       3.6.2   セルフブロードキャスト
       3.6.3   古いアドレスのクリーンアップ
  3.7 データベースに保持されたアドレス
  3.8 コマンドラインで与えられるアドレス
  3.9 テキストファイルで与えられるアドレス
4 他の情報
5 リファレンス
 
1 概要
Satoshiクライアントは数種類の異なる方法で、IPアドレスとノードのポートの発見を行います
1 ノードは様々な方法で自身の外部アドレスを発見する
2 ノードは接続する外部ノードのコールバックアドレスを受信する
3 ノードはIPアドレスを受信するためDNSリクエストを作る
4 ノードはソフトウェアにハードコードされたアドレスを使うことができる
5 ノードは他のノードとアドレス交換をする
6 ノードはデータベースにアドレスをストアし、スタートアップ時にそのデータベースを読む
7 ノードはコマンドラインの引数でアドレスを与えることができる
8 ノードはスタートアップ時にユーザーが与えるテキストファイルからアドレスを読む
 
Timestampはそれぞれのアドレスに対していつそのノードアドレスが最後に確認されたかを記録するために保持される。net.cpp中のAddressCurrentlyConnectedはメッセージをノードから受信した時に必ずTimestampをアップデートする。Timestampは20分以上古くなった時にアップデートされデータベースに保持される
実際にノードに接続する時にどのタイプのアドレスが上位に来るのかについてはNode Connectivityの項目を参照。
最初の項では、”getaddr”メッセージを通して、ノードがどのようにアドレスのリクエストを取り扱うのかについて記す。Timestampの役割を理解することによって、アドレスが発見された方法によってTimestampがなぜそれぞれの方法で保持されるのかがよりクリアになる。
 
2 "getaddr"メッセージの取り扱い"
ノードが”getaddr”リクエストを受信した時に、最初に過去3時間のTimestampを持つアドレスをいくつもっているかをはっきりさせる。次に、それらのアドレスを送信する。しかし、もし3時間以内に2500以上のアドレスがあった場合は、ランダムな選択で約2500個のアドレスを選択する。
 
さあ、ノードがノードアドレスを見つける方法について見てみよう
 
3 発見方法
 3.1 ローカルクライアントの外部アドレス
クライアントは自身のルーティング可能なIPアドレス情報を返すパブリックなWEBサービスを使用する
クライアントはnet.cpp中のThreadGetMyExternalIPと呼ばれるスレッドを走らせる。そこでは外部世界から見えるクライアントのIPアドレスを決定する。
最初に91.198.22.70のポート80(checkip.dyndns.org)に接続を試みる。もし接続が失敗した場合、checkip.dyndns.orgへのDNSリクエストが行われ、そのアドレスへの接続を試みる。次に74.208.43.192のポート80(www.showmyip.com)に接続を試みる。接続に失敗した場合、www.showmyip.comへのDNSリクエストが行われ、そのアドレスへの接続を試みる。
上記で試みられたそれぞれのアドレスに対して、クライアントは接続を試み、HTTPリクエストを送り、適切なレスポンスをリードし、そこからIPアドレスをパースする。もしこれが成功した場合、IPアドレスが返ってくる。IPアドレスは接続しているどれかのノードにアドバタイズされ、スレッドは終了する(???)
 3.2 コールバックアドレスへの接続
ノードが最初の”version”メッセージを受信して、コネクションを開始した時に、ノードは自分のアドレスをリモートにアドバタイズし、リモートが望んだ時にローカルのノードに接続することができるようにします。
もしリモートのバージョンが最新のものであったり、ローカルのノードが1000個のアドレスをまだ持っていない場合、自分のアドレスを送信したのちに、”getaddr”リクエストメッセージをリモートノードに送り、多数のアドレスを得ます。
 3.3 IRCアドレス
バージョン0.6.xからBitcoinクライアントはデフォルトではIRCブートストラッピングは使わなくなっているし、バージョン0.8.2からはIRCブートストラッピングは完全に取り除かれている。以下のドキュメントは過去のバージョンに対する正確性のために記されている
自身のアドレスを知ったりシェアするために、ノードはたのノードをIRCチャンネルを通して他のノードアドレスを知ることができる。 irc.cpp参照。
自分自身のアドレスを知ったのち、ノードは自身のアドレスをニックネームとして使用するための文字列にエンコードします。そして、#bitcoin00と#bitcoin99の間のIRCチャンネルにランダムに参加します。そして、WHOコマンドを発行します。それらが現れたチャンネルのスレッドはラインを読むとチャンネル内の他のノードのIPアドレスをデコードします。ノードがシャットダウンされるまでそれは繰り返します。
クライアントはIRCからアドレスを発見した時に、現在時刻をTimestampとしてアドレスにセットします。ただし、その時にペナルティとして51分が課されます。それはあたかも一時間前に発見されたかのように見えます。
 3.4 DNS Address
スタートアップにおいて、ピアノードの発見が必要な場合、クライアントは他のピアノードのアドレスを知るためにDNSリクエストを発行します。クライアントはDNSサービスのためのシードとなるホストネームを含んでいます。2012,5月17日現在、リストは以下のものを含んでいます(chainparams.cppより)
 
DNS応答は要求された名前に対して複数IPアドレスを含むことができます。
DNSによって発見されたアドレスは最初にTimestampゼロが与えられています。ですので、getaddrリクエストに対する応答でアドバタイズはされません。
 
3.5 ハードコードされたSeedアドレス
クライアントはBitcoinのノードを示すハードコードされたIPアドレスを含んでいます。
これらのアドレスは、他の方法によってアドレスが全く得られなかった時にラストリゾートとしてのみ使われます。接続をハンドリングするThreadOpenConnection2()のスレッドのループでアドレスマップが空だった時、”seed”IPアドレスがバックアップとして使用されます。
可能な時にシードノードを取り除くコードがあります。これらのノードの負荷を下げるためです。ひとたびローカルノードが十分なアドレスを得た時(おそらくシードノードから情報を得た)、シードノードとのコネクションは閉じられます。
シードアドレスは最初はゼロのTimestampが与えられます、それゆえ、”getaddr”リクエストに対する応答ではアドバタイズされません。
 
3.6 addr"アドバタイズメント
getaddrリクエストを送った後にやってくるaddrメッセージによってノードはアドレスを受け取ります。または、ノードが無償でアドレスをリレーするときに要求なしにやってくるaddrメッセージによってノードはアドレスを受け取ります。
もし、アドレスが古いバージョンのリレーからのものであった場合は無視します。もし、そこまで古いバージョンでない場合、もし1000個のアドレスをすでに持っていたら無視します。
または、1000以上のアドレスが送られてきた時も全て無視されます。
addrメッセージで受信したアドレスはTimestampを持っていますが、Timestampを直接使用はしません。
 
メッセージの中のそれぞれのアドレスに対して
      1.もしTimestampが非常に小さかったり、大きかったりした場合、5日前に設定されます
      2.Timestampから2時間を差し引いて、アドレスを追加します。
いかなるアドレスが追加される時でも、いかなる理由によっても、コードはAddAddress()をコールして、すでにアドレスが存在しているかどうかはチェックしません。net.cpp内のAddAddress()関数がそれを実行します。すでにアドレスが存在していても、アドレスのレコードをアップデートします。もし、アドレスのアドバタイズされたサービスが変わっていても(?)、それがアップデートされストアされます。
もしアドレスが過去24時間以内に見られて、Timestampが60分以上古い場合、60分過去にアップデートされます。
もしアドレスが過去24時間以内に見られておらず、Timestampが24時間以上古い場合、24時間過去にアップデートされます。
 
 3.6.1 アドレスリレー
一度アドレスが”addr”メッセージ(上記参照)によって加えられたら、それらは他のノードにリレーされます。最初に以下のような基準が設定されます。
     1.処理が行われた後、アドレスTimestampが現在時刻から60分以内である
  1.       “addr”メッセージは10個、もしくはそれ以下のアドレスを含む
  2. fGetAddrがノードにセットされていない。fGetAddrはfalseからスタートし、ノードにアドレスをリクエストした時にtrueにセットされます。そして、1000以下のアドレスをノードから受け取ったときにクリアされます
  3. アドレスはルーティング可能でないといけない
上記の基準にマッチする全てのアドレスに対して、ノードはアドレスと現在の日にち(Integerで表される)と256bitの乱数(クライアントのスタートアップ時に生成される)をハッシュする。ノードは最もハッシュの小さい値のアドレスを二つ選び、”addr”メッセージをそれらにリレーする。これはそれぞれのノードが”addr”メッセージを与えられたタイミングで二つの他のノードのみにリレーすることを保証する。そしてその二つはランダムに選択されており、ランダムな選択は少なくとも24時間毎に行われることが保証される。
 3.6.2 セルフブロードキャスト
24時間毎に、ノードは自分自身のアドレスを接続している全てのノードにアドバタイズする。
これはまた、リモートノードが持っていると思われるアドレスのリストをクリアーし、ノードのリフレッシュのトリガーとなる(?)。このコードはmain.cppのSendMessages()の中にある。
 3.6.3 古いアドレスのクリーンアップ
main.cppの中のSendMessages()において、古いアドレスをリムーブするコードが存在している。
これは3つのアクティブなコネクションがある限り、10分毎に行われる。
ノードは1000アドレスがマップされ、20秒以上消去プロセスが行われていない限り、14日以上使われていないメッセージを消去する(?)。
 
3.7 データベースに保持されたアドレス
アドレスはAddAddress()がコールされた時にデータベースに保持される。
アドレスははスタートアップの時、AppInit2()がdb.cppに存在するLoadAddresses()をコールした際に読み出される。
現在は、どれか一つのアドレスがストアされるかアップデートされる時は必ず、全てのアドレスが一度に同時にストアされるようになっています。実際のところ、AddAddressはは様々なテストで、0.01秒ほど使用することが分かっており、クライアント実行の最初の12時間で典型的には数万回呼び出されます。
 
3.8 コマンドラインで与えられるアドレス
ユーザーは接続するノードを
-addnode <ip>
のようにコマンドラインの引数で与えることができます。複数のノードが指定できます。
コマンドラインで与えられるアドレスは当初はTimestampゼロが与えられます。それゆえ、”getaddr”リクエストに対する応答でアドバタイズされません。
ユーザは、-connect <ip>コマンドライン引数でも接続するアドレスを与えることができる。複数のノードが指定できます。
-connect引数と -addnode引数の違いは、-connectが指定されたとき、アドレスはアドレスデータベースへ追加されず、ただ単に使用されます。
 
3.9 テキストファイルで与えられるアドレス
クライアントは自動的に bitcoinデータディレクトリにある“addr.txt”という名前のファイルを読み、その中にある、ノードアドレスを追加します。これらのノードは他のアドレスと比較して何の特権もありません。ただ単にプールに追加されます。
テキストファイルからロードされるアドレスは最初にTimestampゼロが与えられます。それゆえ、”getaddr”リクエストに対する応答でアドバタイズされません。
 
  1. 他の参照
Network - Bootstrapping
 
 

EthereumのRelease

いよいよ今週、Ethereumのgenesis blockが生成されて動き始めます。

https://blog.ethereum.org/2015/07/22/frontier-is-coming-what-to-expect-and-how-to-prepare/

安定稼働して商用に使用できるようになるまでには、まだまだ色々起きると思いますが、Decentralizedなコンピュータが動き始める時ということで、もしかしたらITの歴史に残るタイミングになるかもしれません。

Decentralizedなコンピュータが存在し続けることが可能なのか、可能だとしたらそれがEthereumになるのか、誰にも分かりませんが、最初の一歩が動き始めたという感じです。

Ethereumが何かについてはこちらの記事参照。

Ethereum(3) Bitcoin2.0の本命 Ethereumとは何か - Tech と Culture

ビジネスレイヤーとビットコイン

連続してモヤモヤしたエントリ。

前のエントリでblockchainが公共インフラになる可能性を色々考えてみたけど、やっぱり中々難しくて答えが出せない。 もちろん、ただの技術なので公的な所が運用すれば公的だし、会社が利用すればビジネスなんだろうけど。結局kawangoのビジネスレイヤーの話になっていくっていう主題は正しそうな気もする。

はてぶコメントで、「夢想家 vs. 陰謀論すき」ってあって、面白いなーと思った。特にkawangoと闘っている気はないんだけど。自分はこのブログでは夢想家なんだけどそうではない別の部分もある。

自分はエンジニアとして、オープンソースコミュニティに所属している部分と、ビジネスをやっている部分があって、一応、自分の中のルールで誠実と思えるルールで行動している。綺麗に分けられる訳ではないんだけど、ビジネスに関しては当然公開できない情報が多いので、ネット活動はオープンソース活動よりの立ち位置が大半になる。 Ethereumに関して一時期white paperを翻訳したりして活動していたのだけど、途中でどういう立ち位置の組織か良く分からないと感じて引き気味になった。あるタイミングで議論の末、NPOを選んだという発表はあったので何かしらのルールが決まっていると思うけど。

blockchain絡みのことに関しては、オープンソースコミュニティ側の自分から見た興味とビジネス側の自分から見た興味の両方があって、オープンソース側の方だけをブログに書いていたんだけど、kawangoの主題を考えて、やっぱりビジネス側のことも書いた方がいいんじゃないかって気がしてきた。

自分はハードウェア&ソフトウェアの開発者でIoT関連のことをやっている。この分野のビジネスを考えた時に自分が考えつく殆どの製品のビジネスモデルはIDやデータを大量に抑えた会社が勝ちという結論になってしまい、googleamazonにやられて終わるって結論になってしまう。どうやって生き延びるかを四六時中考えている中、「そうならないストーリーがありそう」と感じる唯一の技術がblockchainで、そういう興味がビジネスサイドの自分にははっきりと存在している。

前のエントリで書いたように、インターネット上のIDを全ての会社より上位の存在にして個人の物にするというような社会的なコンセンサスと技術を創り出す可能性が少しあって、もしそれが実現した場合、現在のビジネスの支配関係を変える可能性が出て来る。まあblockchainの使うエネルギー量が大きすぎて何もできないっていう可能性も高いんだけど。。。 公共の物、オープンソースコミュニティの物、ビジネスの物、どれであっても結果を出すための競争があるんだけど、競争の仕方は全然違う。それぞれの立場で社会から認められてユーザーを増やさないといけない。

googlewintelの支配から救うオープンな会社というイメージでどんどん成長した。確かにAndroid OSをオープンソースで公開してその上で活動するdeveloperのエコシステムを作るモデルを提供して素晴らしいと思う。しかし、コアの広告事業は何もオープンにはしていない訳で、支配者のmicrosoftが持っていた武器にオープンソースをぶつけることでその部分をコモディティ化して支配を奪い取ったという見方もできる。それは別に悪いことではなくて、皆そういう競争をしている。 そしてblockchainが現在の支配者達の競争力の源泉をコモディティ化する武器になると考えてシリコンバレーでもとてつもない額の投資が行われているんじゃないかと自分は感じてる。その時に本当に公的なのかビジネスレイヤーの話なのかは真剣にやらないと相手のビジネスモデルに呑み込まれる。それは別に陰謀論でもなんでもなくて、海外の本当に頭のいい連中というのはそういう勝負をしている。技術はそういう勝負の武器のひとつにすぎないと皆捉えている(当然、技術は理解できる前提)。 例えコアサービスが公的なものになったとしても、その周辺にはビジネスが沢山立ち上がる。そしてコアに発言権を持っているか、周辺ビジネスにどれだけ支配力を持っているかが大きな勝負になる。

日本のメディアはビットコインにスゴくnegativeなイメージを付けてしまった。本当にビットコインは投機と金儲けの欲望で作られていて価値はないのか?と考えると自分はそうではないと感じる。かつて大学の先生と話をした時に「通貨の定義は皆が通貨と思うもの。トートロジーな感じだ」という話を聞いて面白いなと思った。ビットコインはkawangoが言うように誠実ではないやり方で思い込ませたのかもしれないけど、現に数千億の価値がついている訳だし、国家の通貨だって、通貨と信用させるために軍隊という暴力を持っている面もある。それにP2Pで価値交換ができるという"実証"を成し遂げた訳で、夢を見せた原動力の一部は本物だ。そしてその創り出した価値から会社が生まれて本当の価値になろうともがいている最中なんじゃないかと思っている。

ビットコインの生み出した価値を完全に利用して、もの凄い額のVCの投資も加わって、本当にゲームチェンジの最大の武器になると考えてチャレンジしに行っている状態なのに、日本はビットコインは犯罪に使われやすいどうのこうのとかくだらないことやっている。くだらないは言い過ぎだけど、チャレンジを萎縮させている。

なので、kawangoの「ビットコイン界隈は欺瞞だ!」っていうことから始まったこの議論を通して、さらにこの状況が悪化しないで欲しいなというのが自分の希望。このタイミングで本当の状況を周知したらいいんじゃないかな。 kawangoだってblockchainのポテンシャルは認めている訳だし、ビットコインが創り出した数千億の価値を日本だけが利用できない状況になると、そこから本物が生まれた時に経済的にボロ負けになってしまう。