2017年4月21日金曜日

macの環境変数設定

久しぶりにいじろうとしたら上手くできなかったので覚え書きとして。

.bash_profileとは

PCを立ち上げたときに実行されるシェルスクリプトの一つ。他にもファイルが存在しているようだが範囲外なので割愛。

.bash_profileの確認手順


ファイルの保存先にカレントディレクトリを移す
    cd ~ #保存先のディレクトリに移動
ディレクトリ内にファイルが存在するかを確認する
    ls -la #隠しファイル含めた全てのファイルを表示
    
    

環境変数の設定と反映手順


ファイルを編集モードにする
    vim .bash_profile #今回追加する環境変数
PATHを追記する
    export PATH="$HOME/.pyenv/shims:$PATH" #今回追加する環境変数
ファイルを更新する
    source ~/ .bash_profile #今回追加する環境変数

2017年4月18日火曜日

"MasteringBitcoin"から読み解くP2SH

前回の記事でごちゃごちゃと勉強して見たもののこちらの章に入ってから何をやっているのかよくわからなくなってきた。なのでもう一度勉強内容を整理するためにMasteringBitcoinで復習したのでその内容を記す。

P2SH(Pay to Script Hash)とは

マルチシグネチャをサポートする機能の一つ。元々のマルチシグネチャは複雑で扱いづらいことは前回も触れたがこの問題を解決するために開発された技術。

P2SH以前の問題


  • 例えばマルチシグでサポートされたウォレットを使って顧客に対して支払いをするシーンを考える
    • このときに我々は顧客にこのscriptについて説明する手間が発生する
    • 顧客はscriptを作ることができる特別なウォレットを使う必要がある(単純に顧客の使用しているウォレットがこの機能をサポートしてなかった場合)
    • 特別なscriptを使ったトランザクションの作り方を理解する必要がある
    • 複数の公開鍵情報を含んでおり単純な支払いトランザクションより高い手数料を取られる

以上のように問題が山積みであったわけだ。

P2SHのアプローチ

簡単に言えば複雑なlocking scriptをハッシュに置き換えて簡素化しようというわけだ。
P2SHは「このハッシュとマッチするscriptに対して支払い、このscriptはのちほどこのアウトプットが使用されるときに与えられます」という意味です。  
Mastering Bitcoin 第5章 P142 
もう少し別の解釈をするとlocking scriptの意味は以下のようになるだろう。
今まで:「M個のキーに対応するマルチシグネチャscriptに対する支払い」
P2SH:「このハッシュを持ったscriptに対する支払い」

 
P2SHとredeem script

P2SHを使用しないscriptと使用するscriptとではredeem scriptの有無が違いとなる。
redeem scriptの中身はハッシュに置き換えられるlocking scriptである。しかしlocking scriptにはそれのハッシュのみしかなく、redeem script本体は実際にアウトプットが使用される時のunlocking scriptの一部として出てくるのみだ。

P2SHアドレス

scriptの20バイトハッシュをBase58Checkエンコードしたものでこれはビットコインアドレスのように使うことができる。ちなみにビットコインアドレスは公開鍵ハッシュのBase58Checkエンコードしたものである。
P2SHアドレスではversion prefixで「5」が使われておりアドレスは「3」から始まる。
こうしてできたP2SHアドレスは顧客に送られ、通常の支払いと同様にウォレットを使うことができるという。

2017年4月16日日曜日

"Programming The Blockchain in C# 日本語"のP2SHでコードを動かしてみた

前回と同様にこちらでの勉強内容を記す。

前章で勉強したマルチシグの作り方の復習

Key bob = new Key();
Key alice = new Key();
Key satoshi = new Key();

var scriptPubKey = PayToMultiSigTemplate.Instance
.GenerateScriptPubKey(2, new[]{bob.PubKey,alice.PubKey,satoshi.PubKey});
Console.WriteLine(scriptPubKey);



ここで得られるマルチシグはビットコインアドレスのように人が区別しやすい形式になっていないとのこと。確かにそうだ。

先ほどの懸案を解消するP2SH

var paymentScript = PayToMultiSigTemplate
            .Instance.GenerateScriptPubKey
            (2, new[]{bob.PubKey,alice.PubKey,satoshi.PubKey}).PaymentScript;
Console.WriteLine(paymentScript);
Console.WriteLine(paymentScript.GetScriptAddress(Network.Main));



  • paymentScriptはマルチシグのハッシュを表しているため、Base58エンコードでBitcoinScriptAddressに変換できるので独自にpaymentScriptAddressを生成して見た。
  • 一番目が"3"担っている。わかりやすい表記にすることができた。


上記と同様にredeemScript.Hash.ScriptPubkeyでも表現できる

Script redeemScript = PayToMultiSigTemplate
.Instance.GenerateScriptPubKey
(2, new[]{bob.PubKey,alice.PubKey,satoshi.PubKey});
Console.WriteLine("redeemScript" + redeemScript);
Console.WriteLine("redeemScriptAddress:" + redeemScript
.Hash.GetAddress(Network.Main));



  • ここで得られるのはBitcoinScriptAddress、つまりマルチシグ用のアドレスと理解しておけば良いだろう
    • このメリットは支払う人がredeemScriptHashについて知っていればいいの
      • つまりredeemScriptのような複雑な情報に触れる必要がなくなる
      • またその中身が誰と誰のマルチシグなのかを知る必要もなくなるということ



  • 疑問が湧いたので記しておく
    • そもそもredeemScriptの必要性はなんなのか?
    • paymentScriptがマルチシグのハッシュであるならばGetScriptAddressでマルチシグ用のアドレスを生成できるのではないか?


receivedというトランザクションにマルチシグが受け取ったコインがあると想定すると

Transaction received = new Transaction();
received.Outputs.Add(new TxOut(Money.Coins(1.0m), redeemScript.Hash));
Console.WriteLine("received.Outputs:" + received.Outputs.Transaction);


受け取ったコインを使いたい時

ScriptCoin coin = received.Outputs.AsCoins().First().ToScriptCoin(redeemScript);
Console.WriteLine(coin.Amount);
Console.WriteLine(coin.CanGetScriptCode);
Console.WriteLine(coin.IsP2SH);
Console.WriteLine(coin.Outpoint);
Console.WriteLine(coin.Redeem);
Console.WriteLine(coin.RedeemType);
Console.WriteLine(coin.ScriptPubKey);
Console.WriteLine(coin.TxOut);


まとめ

redeemScriptとpaymentScriptどちらからも同様のscriptAddressが得られると思っていたがそうではなかった。その理由は解決したらここに追記したい。

2017年4月13日木曜日

デルファイ法

つまりデルファイ効果は、OSカーネル級の複雑なものでも、開発上の複雑さをおさめることができるんだ。
              ー伽藍とバザール エリックレイモンド著

こちらを大いに参考にした。

何なのか

専門家グループなどが持つ直観的意見や経験的判断を反復型アンケートを使って、組織的に集約・洗練する意見収束技法。技術革新や社会変動などに関する未来予測を行う定性調査によく用いられる。

もともとは米軍が「ソ連の立場になってらアメリカに何個の原爆を落とせば良いのか」を考えるための研究から始まったもの

何が良いのか

一般に、専門家同士の意見の集約・合意を得る方法として、会議や審議会、パネルディスカッションといった意見交換法が用いられるが、これらの方法は「グループにおける優位者や権威者、声の大きな者の影響」「テーマと無関係な意見、反対のための反対」「意見の統一に対する圧力」などによる偏りが考えられる。

つまり「目上の人には逆らえない」とか「何かしら意見まとめなければ」といった空気読め感やプレッシャーにさらされない意見が専門家から聞けますよということ。

何が課題か

デルファイ法の問題としては「専門家の定義や選出方法」「アンケート質問の適正さ」「意見一致への強要や誘導」「集約手法の信頼性や妥当性」「未来予測の限界」などが指摘される。デルファイ調査を実施する際には、手法に内在する限界を十分に理解したうえで、適切に行うことが必要である。
あくまでも”手法”なので、適切に使おうよということ。専門家の定義とかは揉めるとこかなと。

2017年4月9日日曜日

テクニカルリファレンスから読み解くNEM

こちらを参考にNEMに対してまずは自分なりの解釈を持ちつつ、公式フォーラムの情報から理解を深めていく。

NEMの目標

NEMの目標はセキュリティと信用の必要ない計算機構として注目されている暗号通貨のエコシステムの基盤となることです。NEMはマルチシグトランザクションと暗号化メッセージを標準機能としてサポートする形でローンチしました。加えて、NEMのピア・ツー・ピア(P2P)ネットワークは、悪意あるノードの影響を特定し最小化するために、Eigentrust++に修正を加えたものを実装しています。
NEMは進化途中で始まったばかりです。これから起こる出来事にご期待ください。
暗号通貨のエコシステムの基盤となる、というわかりやすい目標。
BitcoinBlockchainに取って代わるということだと理解する

新しい概念


  • アカウント
  • POI(Proof of Importance)


アカウント

以下のような情報が紐づけられているらしい
アカウントには以下の情報が紐づけられており、これをアカウントの状態(state)と呼びます。
それぞれについて調べていく。

バランスシート

これは調べるまでもなくそのアカウントが保有するXEMの量のはず

収穫したブロック数


  • BitcoinBlockchainと同様にNEMにはブロックやトランザクションという概念が存在する
  • またBlockを作成する過程も当然存在する
    •  それをハーベスティング(収穫)という
  • 収穫をするアカウントには手数料が支払われる
    •  つまり基軸通貨の価値を前提としたインセンティブ方式である
  • 収穫をするには最低残高が10000XEM必要


ブロック作成するアカウントを決定するために以下の計算がなされるという
  • $hit = 2^{54}|ln(\frac{h}{2^{256}})|$
  • $target = 2^{64}\frac{b}{d}t$ 
※この数式を書くにあたりMathJaxという存在を初めて知った

$hit<target$を満たすときアカウントは新しいブロックを作成できるという
ちなみに上記の計算には以下の変数が使用されるようだ
  • h = H(前ブロックのジェネレーションハッシュ値、アカウントの公開鍵) ... 256-bitの整数
  • t =前ブロックからの時間(秒)
  • b = 8999999999 * (アカウントの重要度)
  • d =新しいブロックの作成難度

  • ブロックを生成の確率はbのアカウントの重要度でコントロールするしかないようだ
     重要度を高めても支配的なものにはならなそうだが・・・

    ここでふと疑問が湧く。「たくさんアカウントを作れば確率が上がるのでは?」と。
    しかしそこについては以下のように釘が刺されていた。
    また、hitは指数関数的に分布する点にも注意してください。したがって、重要度がたくさんのアカウントにわけられている時でも新しいブロックを作成する確率は変わりません。

    そのアカウントが最初に参照されたトランザクションの含まれるブロック高

    おそらくアカウントを作ってから一番最初に生成したトランザクションが含まれるブロック高のことだろう。
    己のNanoWalletで確認したブロック高が以下だった。


    マルチシグアカウントリストと共同署名者リスト

    己のマルチシグアカウントの情報とそこに名を連ねている共同署名者リスト

    重要度を委任されたアカウントの情報

    デリゲートハーベスティングを有効化しているかどうか

    重要度とNCDawareRank

    • ブロックの生成のためのアルゴリズムであるPOIに含まれる概念
      •  重要度は以下の情報を計算に用いる
    1. 権利確定済みの残高(vested balance)
    2. 送金されたXEM
    3. トランザクショングラフのトポロジーの情報
      •  NCDawareRankはgoogleのweb検索結果に用いられるアルゴリズム(PageRank)に近いものととりあえず捉えてみる
      •  リファレンスにはNCDawareRankについて以下のような文言があるのであながち間違いではないはずだ
    \muが加えられたことを除けば、この定義はPageRankと同様です。 NEMの場合、\etaは0.7、\muは0.1です。以下ではそれぞれの変数がいかにして計算されるかを説明します。

    権利確定した(vested)残高(PoIやNEMそのも)
    これはBitcoinBlockchainと同様にトランザクションの状態が承認・非承認とあり承認されたもの≒権利確定した(vested)XEMの残高と捉えれば良いはず

    まとめ(非常に苦しいが・・・)

    ちょろっとさわりだけでも理解しとこうという軽い気持ちでテクニカルリファレンスを読んで見たが、随所に高度な数学知識が散りばめられていて、理論を理解するのはかなりレベルが高そうだった。NanoWallet使いながら徐々に理解を深めていければ良しとしよう。

    "Programming The Blockchain in C# 日本語"のマルチシグでコードを動かしてみた

    前回と同様にこちらでの学習内容を記す。

    ビットコインを使うためn個の異なる公開鍵に対してm個の秘密鍵で署名する必要があるscriptPubKeyを作る

    署名に関わる人たちの鍵を作る

    Key bob = new Key();
    Key alice = new Key();
    Key satoshi = new Key();

    var scriptPubKey = PayToMultiSigTemplate.Instance.GenerateScriptPubKey(2, new[]{bob.PubKey,alice.PubKey,satoshi.PubKey});
    Console.WriteLine(scriptPubKey);

    • 今回はn=3、m=2を想定するようで人数分の鍵を新たに生成する
    • 生成したそれぞれの秘密鍵から公開鍵を生成する
    • 生成された公開鍵からscriptPubKey(LockingScript)を生成する
    •  "2"というのは2つの署名で解除できるということだろうか?


    出力結果
    • このscriptPubKey内容を順に解釈すると以下になるか?
      •  解除には2つの署名が必要
      •  署名できるアカウントの公開鍵ハッシュ(今回のケースでは3つ)
      •  3つのアカウントに対するマルチシグチェックをする


    receivedというトランザクションでビットコインを受け取ったと想定したときこのアウトプットに先ほど作成したscriptPubKeyを含める

    var received = new Transaction();
    received.Outputs.Add(new TxOut(Money.Coins(1.0m), scriptPubKey));

    先ほど定義したトランザクションから受け取ったコインを取得する
    Coin coin = received.Outputs.AsCoins().First();

    まだ署名されていないトランザクションを生成する
    BitcoinAddress nico = new Key().PubKey.GetAddress(Network.Main);
    TransactionBuilder builder = new TransactionBuilder();
    Transaction unsigned = builder.AddCoins(coin)
               .Send(nico, Money.Coins(1.0m)).BuildTransaction(sign: false);


    • トランザクションを生成するためのnicoのアドレスを生成する
    • トランザクションビルダーを生成する
    • 生成したトランザクションビルダーに必要な情報を付与する
      •  先ほど取得したコイン
      •  送り先と送るコインの量
      •  署名の有無


    生成した署名されてないトランザクションにaliceがどのように署名するかを示す

    Transaction aliceSigned = builder.AddCoins(coin)
    .AddKeys(alice).SignTransaction(unsigned);

    • aliceがトランザクションに署名するために必要な情報を付与する
      •  先ほど取得したコイン
      •  aliceの鍵
      •  先ほど定義した署名されてないトランザクション


    このaliceSignedの中身は以下となる

    bobの分も同様に行う

    Transaction bobSigned = builder.AddCoins(coin)
                 .AddKeys(bob).SignTransaction(aliceSigned);

    • bobがトランザクションに署名するために必要な情報を付与する
      •  先ほど取得したコイン
      •  bobの鍵
      •  先ほど定義したaliceの署名がされたトランザクション



    先ほどのscriptSigにaliceのものに加えてbobのものが追加されている

    しかしこれでは署名が結合されていないらしいので両者の署名を一つにする

    Transaction fullySigned = builder.AddCoins(coin)
                       .CombineSignatures(aliceSigned,bobSigned);

    その結果の署名が以下になる

    • 何も変わってない・・・。
    • 一度サイトの方を読み返してみると色々とおかしな点に気づく
    • bobの署名に関する図解がコードと異なっている
      •  coinとsatoshiの秘密鍵と署名されてないトランザクションが必要となっている
      •   正確にはcoinとbobの秘密鍵とaliceが署名したトランザクションが必要ではないか?
      •  しかしそれだと今回の結果通り署名の結合が意味をなさない
    • bobの署名には正しくは以下が必要なのではないかと考える
      •  aliceのトランザクションではなくunsignedなトランザクション
      •  satoshiの鍵ではなくbobの鍵

    まとめ

    上記の疑問通りコードを書き直したがbobSignedとfullySignedに変化はなかった
    この署名の結合の意味はなんなのか、わからずじまいだった。新しいことがわかり次第追記していきたい。

    2017年4月4日火曜日

    "Programming The Blockchain in C# 日本語"のP2WPKH (Pay to Witness Public Key Hash)でコードを動かしてみた

    前々回と同様にこちらでの学習内容を記す。

    前準備

    前回のSegwit調査内容が活かされるので各自で確認をしておく。
    Segwitが何たるかはこちらリンクを参考にしてほしい。

    scriptPubKeyからP2PKHとP2WKHの違いを確認する

                var key = new Key();
                Console.WriteLine("P2PKH : " + key.PubKey.ScriptPubKey);
                Console.WriteLine("P2WKH : " + key.PubKey.WitHash.ScriptPubKey);

    出力は以下となった。

    まとめ

    • このP2WKHで得られた結果がinputもしくはoutpointのscriptSigではなくwitnessに入っているらしい。
      • つまりこれが署名データということ。
    • ちなみに出力の0はwitnessのバージョンを表すらしい。
    • P2WKHはP2PKHと同じ文法で署名チェックをするようだ。
    • 署名は悪意のあるユーザーもしくは間違いによって修正されうるscriptSigには含まれなくな流のでmalleability対策となるようだ。


    追記

    • 2017年4月4日 0:14 出力結果の表示不具合を修正

    2017年4月2日日曜日

    [和訳]Segregated Witness Benefits_BitcoinCore

    こちらを勉強するに当たって知っておいた方が良さそうだったのと、後で調べたいと思った人が英語で挫折しないようにと思い翻訳しながら理解を深めていく。

    対象サイトはこちら


    segwitのメリット

    The Segregated Witness soft-fork (segwit) includes a wide range of features, many of which are highly technical. This page summarises some of the benefits of those features.
     segwitは高度に技術的なものも含めて多くの広範囲に及ぶ特徴を含んでいる。このページではそれらの特徴が持つメリットのうちのいくつかを要約する。

    Malleability(展性)修正

    Bitcoin transactions are identified by a 64-digit hexadecimal hash called a transaction identifier (txid) which is based on both the coins being spent and on who will be able to spend the results of the transaction.
     ビットコイントランザクションはコインが使われたことや誰がそのコインを使うことができるのかといった情報に基づく64bitの16進数ハッシュからなるトランザクション識別子(txid)と呼ばれている。
    Unfortunately, the way the txid is calculated allows anyone to make small modifications to the transaction that will not change its meaning, but will change the txid. This is called third-party malleability. BIP 62 (“dealing with malleability”) attempted to address these issues in a piecemeal manner, but was too complicated to implement as consensus checks and has been withdrawn.
    残念なことにtxidが計算される方法はトランザクション自体が持つ意味は変えずにtxidを変えるということを誰かにできるようにさせてしまう。これをサードパーティMalleabilityという。BIP62ではこれらの問題に断片的に働きかけようとしていたがこれはコンセンサスチェックのように実装するのがとても複雑だったので撤回されてしまった。

    For example, you could submit a transaction with txid ef74…c309 to the network, but instead find that a third-party, such as a node on the network relaying your transaction, or the miner who includes your transaction in a block, modifies the transaction slightly, resulting in your transaction still spending the same coins and paying the same addresses, but being confirmed under the completely different txid 683f…8bfa instead.
    例えばあなたが"ef74...c309"というtxidを持ったトランザクションをネットワークに伝搬できたとしてもあなたのトランザクションに依存するネットワーク上のノードやあなたのトランザクションをブロックに含んでいるようなマイナーといった第三者がトランザクションをわずかに、あなたのトランザクションが未だに同じコインを同じアドレスに向けて消費してるように、変更するが完全に異なるtxid"683f...8bfa" の元で確認されることとなる。

    私見)トランザクションに依存するネットワーク上のノーどとはSPVクライアントのことか?
    More generally, if one or more of the signers of the transaction revise their signatures then the transaction remains valid and pays the same amounts to the same addresses, but the txid changes completely because it incorporates the signatures. The general case of changes to signature data (but not the outputs or choice of inputs) modifying the transaction is called scriptSig malleability.
    より一般的にいうと、もしトランザクションの署名者の一人もしくは複数が彼らの署名を修正するとトランザクションは有効で同量を同じアドレスに支払うことができるがこの行為は署名を組み込んでしまうためtxidは完全に変更されてしまう 。この一般的な署名データがトランザクションを修正することに対する変更事例(アウトプットやインプットを選ぶことではない)はscriptSig malleabilityと呼ばれている。

    私見)txidは署名を含めたトランザクション全体のハッシュ値であるということ


    Segwit prevents third-party and scriptSig malleability by allowing Bitcoin users to move the malleable parts of the transaction into the transaction witness, and segregating that witness so that changes to the witness does not affect calculation of the txid.
     segwitはビットコインユーザーによるサードパーティもしくはscriptSigのmalleabilityを対してトランザクションにおける展性的な部分をトランザクションwitnessに移動させることで妨げることができるしwitnessの分離によってtxidの計算とwitnessを無関係にさせる変更である。

    私見)訳がヘンテコであるが、witnessをtxidの計算に含めないことによってtxidの変更による混乱を避けることができるということだろう。

    誰の利益になる?

    • Wallet authors tracking spent bitcoins: it’s easiest to monitor the status of your own outgoing transactions by simply looking them up by txid. But in a system with third-party malleability, wallets must implement extra code to be able to deal with changed txids.
    使われたビットコインを追跡するウォレット作成者:単にtxidで探されるあなたの伝搬されようとしているトランザクションの状態を観察することが容易になる。しかしサードパーティmalleabilityの存在するシステムだとウォレットは変更されたtxidを扱うための余分なコードを実装しなければならない。
    • Anyone spending unconfirmed transactions: if Alice pays Bob in transaction 1, Bob uses that payment to pay Charlie in transaction 2, and then Alice’s payment gets malleated and confirmed with a different txid, then transaction 2 is now invalid and Charlie has not been paid. If Bob is trustworthy, he will reissue the payment to Charlie; but if he isn’t, he can simply keep those bitcoins for himself.
    未確認のトランザクションを使用しようとしている誰か:もしアリスがトランザクション1でボブに支払う場合、ボブはそれをトランザクション2のチャーリーに対する支払いで使う、そしてその時アリスの支払いは展延され異なるtxidで確認される、その時トランザクション2は無効になってチャーリーは支払いを受けられなくなった。もしボブが信頼できるなら、彼はチャーリーに対する支払いを再発行するだろうがもし彼がそうでなければ彼はそれらのビットコインを彼自身で保持することができてしまう。
    • The Lightning Network: with third-party and scriptSig malleability fixed, the Lightning Network is less complicated to implement and significantly more efficient in its use of space on the blockchain. With scriptSig malleability removed, it also becomes possible to run lightweight Lightning clients that outsource monitoring the blockchain, instead of each Lightning client needing to also be a full Bitcoin node.
    ライトニングネットワーク:サードパーティmalleabilityとscriptSig malleabilityが修正されるとライトニングネットワークは実装するのに複雑でなくなるしブロックチェーン上のスペース利用において明らかに効率的になる。scriptSig malleabilityが除去されると、フルビットコインノードになることが必要とされている高速クライアントの代わりにブロックチェーンの監視をアウトソースする軽量かつ高速なクライアントを実行できるようになる。
    • Anyone using the block chain: smart contracts today, such as micropayment channels, and anticipated new smart contracts, become less complicated to design, understand, and monitor.
     ブロックチェーンを使ういずれの人も:マイクロペイメントチャネルのような今日のスマートコントラクトや高度化された新たなスマートコントラクトをデザインし理解し観察することが今より複雑でなくなる。

    • Note: segwit transactions only avoid malleability if all their inputs are segwit spends (either directly, or via a backwards compatible segwit P2SH address).

    注記:segwitトランザクションは全ての入力がsegwitによるものである場合のみmalleabilityを回避できる。(直接、または介護完成のあるsegwit P2SHアドレス経由)


    まとめ

     segwitの目的と手段はおおよそ理解できた。しかし現在の展性対策としてのextra codeとは一体どのようなもので、それがネットワークに及ぼす定量的な影響度合いについて理解できなかった。そこは今後要調査である。

    "Programming The Blockchain in C# 日本語"のP2PK[H] (Pay to Public Key [Hash])でコードを動かしてみた

    前回に引き続きこちらのサイトで練習。
    P2PK(Pay to Public Key)とP2PKH(Pay to Public Key Hash)の違いについて学ぶ。

    前準備

    こちらでScriptPubKeyに関する説明がされている。
    ひょっとすると知らないかもしれないが、実は、ビットコインのブロックチェーンの内部には、ビットコインアドレスなどというものはない。内部的に、ビットコインのプロトコルでは、ビットコインを受け取る相手をScriptPubKeyで認識することになっている。
    つまりビットコインの所有権を誰が持っているのかをScriptPubKeyで認識するということ。一般的にはビットコインアドレスがその一旦を担ってい流ように思われがちだがそうではないということ。

    本編


    公開鍵とビットコインアドレスの関係性を復習

                var publicKeyHash = new Key().PubKey.Hash;
                    //公開鍵ハッシュ値を生成
                var bitcoinAddress = publicKeyHash.GetAddress(Network.Main);
                    //公開鍵ハッシュ値からメインネット用のビットコインアドレスを生成
                Console.WriteLine(publicKeyHash);
                Console.WriteLine(bitcoinAddress);

    • ビットコインアドレスは公開鍵ハッシュから生成される


    ビットコインアドレスとScriptPubKeyの関係性を把握

                var scriptPubKey = bitcoinAddress.ScriptPubKey;
                    //ビットコインアドレスからLockingScript(ScriptPubKey)を生成
                Console.WriteLine(scriptPubKey);

                var sameBitcoinAddress = scriptPubKey.GetDestinationAddress(Network.Main);
                    //LockingScriptからビットコインアドレスを生成
                Console.WriteLine(sameBitcoinAddress);

    • ScriptPubKeyはビットコインアドレスから生成される
    • その逆もまた然り


    しかし必ずしもScriptPubKeyはビットコインアドレスを含んでいる訳ではない。というのがここで主張されていることだ。

    GenesisBlockから見るScriptPubKeyの性質

                Block genesisBlock = Network.Main.GetGenesis();
                    //GenesisBlockを取得
                Transaction firstTransactionEver = genesisBlock.Transactions.First();
                    //GenesisBlockのトランザクション情報
                var firstOutputEver = firstTransactionEver.Outputs.First();
                    //GenesisBlockのトランザクションのアウトプットを取得
                var firstScriptPubKey = firstOutputEver.ScriptPubKey;
                    //GenesisBlockのトランザクションのアウトプットのScriptPubKeyを取得
                var firstBitcoinAddressEver = 
                    firstScriptPubKey.GetDestinationAddress(Network.Main);
                    //GenesisBlockのトランザクションのアウトプットの
                          //ScriptPubKeyからビットコインアドレスを生成
                
                Console.WriteLine(firstTransactionEver);
                    //scriptPubKeyの形式が「公開鍵ハッシュ値+スクリプト」ではなく
                         //「公開鍵+スクリプト」となっている
                    //初期の頃は公開鍵が直接scriptPubKeyに使われているということがわかる
          
                var key = new Key();
                Console.WriteLine("pay to public key : " + key.PubKey.ScriptPubKey);
                Console.WriteLine();
                Console.WriteLine("pay to public key hash : " + key.PubKey.Hash.ScriptPubKey);


    • ScriptPubKeyの形式が「公開鍵ハッシュ値+スクリプト」ではなく「公開鍵+スクリプト」となっている
    • 初期の頃は公開鍵が直接ScriptPubKeyに使われていたということがわかる。


    まとめ

    P2PKtpP2PKHの違いはScriptPubKeyが公開鍵か公開鍵ハッシュを含んでいるかが大きな違いであることがわかった。

    しかし以下の文章については疑問が残る。P2PKHの採用が量子コンピュータへの対策に繋がるとのことだがなぜそう言えるのだろうか?現在調査中なのでわかり次第追記したい。

    • 楕円曲線暗号(公開鍵秘密鍵 に使われれている暗号)が、楕円曲線上の離散対数問題を解くために改良されたショアのアルゴリズムによって解かれてしまうから。簡単に言うとそれが意味するのは、理論上、量子コンピューターがそう遠くない未来に 公開鍵から秘密鍵を導出できてしまう ということだ。ビットコインを使うときだけ公開鍵を公開することによって、そういった攻撃を無力化することができる(一度使われたビットコインアドレスを二度と使わない前提だが)。





    2017年4月1日土曜日

    "Programming The Blockchain in C# 日本語"のトランザクションパートで実際に送金してみた

    前回に引き続きこちらのサイトで練習。

    今回はサイトの情報を元に自身のハードウォレットのアドレス-今回作成したアドレス間でのBTCのやりとりを実践した。以下はそのイメージ。


    以下の流れで振り返る。
    コードの中に書いてある赤字は疑問点。解消された時に覚えてれば書き換える。

    前準備

    • 今回ハードウォレットからBTCを受け取るアドレスの生成
           //今回取引先として使うアドレスの生成
                var network = Network.Main;
                var privateKey = new Key();
                        //単なるオブジェクト生成?
                var bitcoinPrivateKey = privateKey.GetWif(network);
                //秘密鍵生成、Wallet Important Format、ネットワーク情報を含む
                var address = bitcoinPrivateKey.GetAddress();//
                Console.WriteLine(privateKey);
                Console.WriteLine(bitcoinPrivateKey);
                //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(生成される秘密鍵)
                Console.WriteLine(address);
                        //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(秘密鍵から生成されるアドレス)
    • ネットワークはメインネットを選択
    • privateKeyオブジェクトを生成
    • privateKeyオブジェクトにネットワーク情報を含むWIFの秘密鍵を定義する
    • 秘密鍵からアドレスを生成する
    • 生成したアドレスの記録
                //先ほど作成した秘密鍵とアドレスを別の変数に定義
                var bitcoinPrivateKey1 = new BitcoinSecret
                    ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
                 //秘密鍵をByte文字列に変換?
                var network1 = bitcoinPrivateKey1.Network;
                var address1 = bitcoinPrivateKey1.GetAddress();
                 //改めて定義する必要は秘密鍵をByte文字列に変えたからか?
                Console.WriteLine(network1);
                Console.WriteLine(address1);
    • 秘密鍵をByte文字列に変換
    • ネットワークがメインかテストか秘密鍵から判断(この変数は以降使わない)
    • 秘密鍵よりアドレスを生成
    • ハードウォレットから生成したアドレスに対して送金する
    ここは各自で対応する
    • 送金によって発生したトランザクションIDを取得する

                //取引を行ったトランザクションのIDを取得
                var client = new QBitNinjaClient(network);
                var transactionId = uint256.Parse
                    ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
                var transactionResponse = client.GetTransaction(transactionId).Result;
                Console.WriteLine(transactionResponse.TransactionId);
                Console.WriteLine(transactionResponse.Block.Confirmations);

    • トランザクションIDのハッシュ化
      • uintの中身はこちら
      • SipHashという衝突回避のための関数を使っているらしい
    • トランザクション情報の取得
      • どんな情報が入っているかはblockchain.infoなどからも見られる

    新しいトランザクションの作成そして伝搬

    • receivedCoins、つまりUTXOを定義する
    var receivedCoins = transactionResponse.ReceivedCoins;
                OutPoint outPointToSpend = null;//OutPointの空オブジェクトを作成

                foreach(var coin in receivedCoins)
                {
                    if (coin.TxOut.ScriptPubKey == bitcoinPrivateKey1.ScriptPubKey)
                    {
                        outPointToSpend = coin.Outpoint;
                    }
                }
    • receivedCoins、つまりUTXOをトランザクションレスポンスから取得する
    • 空のアウトポイントオブジェクトを定義する
    • receivedCoins内に含まれるUTXOの数だけ繰り返し処理をする宣言
    • もしトランザクションアウトプット内のScriptPubKeyが秘密鍵に含まれるScriptPubKeyと同じかどうかの分岐処理を宣言
    • もしif文がTrueならばアウトポイントはUTXO内のアウトポイントとする
    • アウトポイントnullに対するエラー対策
    //アウトポイントがnullの場合、エラー対策と認識している
                if (outPointToSpend == null)
                    throw new Exception
                        ("error:どのトランザクションアウトプットもScriptPubkeyを持っていない");
                Console.WriteLine("{0}番目のアウトポイントを使いたい。",outPointToSpend.N + 1);
    • outPointToSpendがnullの場合、つまり正しいOutPointかどうかの見極めをしている
    • 新しいトランザクションインプットの作成
    //トランザクションのOutPointをPrevOutとし、そのPrevOutをインプットトランザクションとする
                var transaction = new Transaction();
                transaction.Inputs.Add(new TxIn()
                {
                    PrevOut = outPointToSpend
                });

    • transactionOutpointが今回作成するtransactionのPrevOutであると定義する
    //BTCを自分のアドレスに送り返すためのInputトランザクションを作る
                var myAddress1 = BitcoinAddress.Create("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
                transaction.Inputs[0].ScriptSig = address1.ScriptPubKey;
                transaction.Sign(bitcoinPrivateKey1false);

    • BitcoinAddressを生成する
    • トランザクションのインプットに含めるScriptSigをアドレスとScriptPubKeyから生成する
    • トランザクションの署名欄に秘密鍵から署名を作る

    • 新しいトランザクションアウトプットの作成
    //受け取ったアドレスから送ったアドレスにBTCを送り返すためのOutputsトランザクションを作成
                var myAddress = new BitcoinPubKeyAddress
                             ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
                TxOut myTxOut = new TxOut()
                {
                    Value = new Money((decimal)0.0004MoneyUnit.BTC),
                    ScriptPubKey = myAddress.ScriptPubKey
                };

                transaction.Outputs.Add(myTxOut);
    • 公開鍵からアドレスを生成する
    • 送金する額を指定する
    • ScriptPubKeyをアドレスから生成する
    • ここで定義したトランザクションアウトプットをアウトポイント

    • メッセージの作成
    //メッセージ送信
                var message = "Thanks";
                var bytes = Encoding.UTF8.GetBytes(message);
                transaction.Outputs.Add(new TxOut()
                {
                    Value = Money.Zero,
                    ScriptPubKey = TxNullDataTemplate.Instance.GenerateScriptPubKey(bytes)
                          //ここでScriptPubKeyを生成する意味は??
                });
    • トランザクションに添えるメッセージを定義する
    • メッセージをバイト文字列にエンコーディングする
    • このメッセージもトランザクションアウトプットの一つとされるがBTCを含まないものとしたいので金額を0とする

    • 新しいトランザクションの伝搬


    //トランザクションを伝播させる
                BroadcastResponse broadcastResponse = client.Broadcast(transaction).Result;

                if (!broadcastResponse.Success)
                {
                    Console.WriteLine("ErrorCode: " + broadcastResponse.Error.ErrorCode);
                    Console.WriteLine(transaction.GetHash());
                           //なんのために取得するのか?
                }

    • BroadcastResponseという型のオブジェクトを用意する。これにはクライアント(自分)からブロードキャストしたトランザクションに対する結果を含めるとする
    • もしブロードキャストが成功しない場合の条件分岐
    • エラーコードを出力する
    • トランザクションハッシュを取得する

    • まとめ
    トランザクション生成からブロードキャストに到るまでの大まかな流れは理解できなかったがScriptPubKeyの使い方がところどころ不明だったのは理解が不十分なところだと思うので何かしらの復習をしよう。