├── .gitignore ├── README.md ├── SUMMARY.md ├── assets ├── BitcoinAddress.png ├── BitcoinAddressToScriptPubKey.png ├── BitcoinCoreTransaction.png ├── BitcoinSecret.png ├── BookQr.png ├── CeoMarketingAccounting.png ├── Coinprism.png ├── Coinprism2.png ├── ColorMaker.png ├── ColoredCoin.png ├── ColoredTransaction.png ├── Derive1.png ├── Derive2.png ├── DeriveKeyPath.png ├── EncryptedKey.png ├── EncryptedKeyResult.png ├── EphemKey.png ├── ExtKey.png ├── ExtPubKey.png ├── FetchColors.png ├── FetchColors2.png ├── IColoredCoinTransactionRepository.png ├── NicoWallet.png ├── NonHardened.png ├── OutPoint.png ├── PPKH.png ├── PassphraseCode.png ├── PassphraseCodeToEncryptedKeys.png ├── Power2Alice.png ├── PowerCoin.png ├── PowerCoin2.png ├── PowerCoin3.png ├── PowerCoin4.png ├── PowerCoin5.png ├── PrivKeyPubKey.png ├── PrivateKey.png ├── ProgrammingBlockchain.png ├── PubKeyHashToBitcoinAddress.png ├── PubKeyToAddr.png ├── PubKeyToScriptPubKey.png ├── QBitNuGet.png ├── RawTx.png ├── ReceiverStealth.png ├── RedeemScript.png ├── RootKey.png ├── ScannerRecover.png ├── ScriptCoin.png ├── ScriptCoinFromCoin.png ├── ScriptPubKey.png ├── SignedTransaction.png ├── SpendTx.png ├── StealthAddress.png ├── StealthCoin.png ├── StealthMetadata.png ├── ThirdPartyKeyGeneration.png ├── TransactionBuilder.png ├── TransparentWallet2.png ├── Trezor.png ├── TxIn.png ├── TxOut.png ├── Visio │ └── BIP32.vsd ├── aliceSigned.png ├── bitcoin.png ├── bobSigned.png ├── ccasa3u.png ├── coin.png ├── encrypted_key.png ├── fullySigned.png ├── nuget.png ├── nuget_jp.png ├── segwit.png ├── visualstudio_enablesourceserversupport.png └── visualstudio_enablesourceserversupport_jp.png ├── bitcoin_transfer ├── README.md ├── bitcoin_address.md ├── blockchain.md ├── payment_script.md ├── private_key.md ├── proof_of_ownership_as_an_authentication_method.md ├── spend_your_coin.md ├── the_blockchain_is_more_than_just_bitcoin.md └── transaction.md ├── cover.md ├── foreword.md ├── implementations ├── README.md └── hiddenbitcoinkey_storage_hd_wallet_md.md ├── introduction ├── README.md ├── complementary_reading.md ├── crowdfunding_this_book.md ├── diagrams.md ├── license_cc_asa_3u.md ├── pre-requisites.md ├── project_setup.md ├── why_blockchain_programming_and_not_bitcoin_program.md ├── why_c.md └── why_do_people_hate_bitcoin.md ├── key_generation └── key_generation.md ├── other_types_of_asset ├── README.md ├── colored_coins.md ├── issuing_an_asset.md ├── liquid_democracy.md ├── proof_of_burn_and_reputation.md ├── ricardian_contracts.md ├── transfer_an_asset.md └── unit_tests.md ├── other_types_of_ownership ├── README.md ├── arbitrary.md ├── multi_sig.md ├── p2pk[h]_pay_to_public_key_[hash].md ├── p2sh_pay_to_script_hash.md ├── p2w_over_p2sh.md ├── p2wpkh_pay_to_witness_public_key_hash.md ├── p2wsh_pay_to_witness_script_hash.md └── using_the_transactionbuilder.md ├── second_communitry_edition.md └── security └── protecting_your_private_keys.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Node rules: 2 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 3 | .grunt 4 | 5 | ## Dependency directory 6 | ## Commenting this out is preferred by some people, see 7 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git 8 | node_modules 9 | 10 | # Book build output 11 | _book 12 | 13 | # eBook build output 14 | *.epub 15 | *.mobi 16 | *.pdf 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](assets/ProgrammingBlockchain.png) 2 | 3 | [コードサンプルはこちら。](https://github.com/ProgrammingBlockchain/ProgrammingBlockchainCodeExamples/) 4 | 5 | ## [この本を読むにはこちら](https://programmingblockchain.gitbooks.io/programmingblockchain-japanese/content/) 6 | 7 | ## コミュニティ 8 | [![Gitter](https://badges.gitter.im/MetacoSA/NBitcoin.svg)](https://gitter.im/MetacoSA/NBitcoin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 9 | 10 | ## 他の言語版 11 | 英語 12 | [Read](https://programmingblockchain.gitbooks.io/programmingblockchain/content/)- [GitHub](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain) - [GitBook](https://www.gitbook.com/book/programmingblockchain/programmingblockchain) 13 | 14 | インドネシア語: [Read](https://nopara73.gitbooks.io/programmingblockchainindonesian/content/) - [GitHub](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain-Indonesian) - [GitBook](https://www.gitbook.com/book/nopara73/programmingblockchainindonesian) 15 | 16 | ## 筆者にフィードバックしたいときは 17 | 18 | もし読んでいて間違いを発見してご自分で修正しない場合は[Github](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese)で課題を提起してください。もしGitBookで読んでいる場合は、インラインでコメントすることも可能です。 19 | 20 | なお、Programming The Blockchain in C\#は英語が原語版であるため、英語版に対して修正があったときは適宜日本語版にも反映します。 21 | 22 | ## 誤記を訂正するには 〜簡単にコミュニティへ貢献するには〜 23 | 24 | 1. [Githubでこの本のページ](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese)にアクセスする 25 | 2. フォークする 26 | 3. 編集する 27 | 4. プルリクエストする 28 | 29 | ## 新しい章を追加する方法 〜さらなるコミュニティへの貢献〜 30 | 31 | 1. [Githubでこの本のページ](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese)にアクセスする 32 | 2. フォークする 33 | 3. フォークしたレポジトリをクローンする 34 | 4. [Gitbook editor](https://www.gitbook.com/editor)をダウンロードしてインストールする 35 | 5. Gitbook editorを起動する 36 | 6. フォークしてクローンしたディレクトリを選択してインポートする 37 | 7. 本を編集する 38 | 8. 保存して同期する 39 | 9. プルリクエストする 40 | 41 | ## 学習プロセスをより良くするためには 42 | 43 | 読みながら修正や追加を通じた貢献をすることで、より早く身につきます。どこかで理解することに悪戦苦闘した場合、後続の読者のためにもわかりやすく言い換えてプルリクエストしてください。 44 | 45 | [課題解決](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/issues)に協力することもできます。(大学生のためのアドバイスですが、就活には卒業証明書よりもGitHubでの活躍のほうが役に立ちます。) 46 | 47 | # 私たちへの寄付 48 | 49 | このアドレスへのすべての寄付が、[こちらのサイト](http://n.bitcoin.ninja/)で公開されます。 50 | 51 | ![1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB](assets/BookQr.png) 52 | 53 | [1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB](https://www.smartbit.com.au/address/1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB) 54 | 55 | ## リンク 56 | 57 | [GitHubでこの本を見る](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese) 58 | [GitBookでこの本を見る](https://www.gitbook.com/book/programmingblockchain/programmingblockchain-japanese)(PDF版、epub版、mobi版でダウンロードもできます) 59 | [コードサンプル](https://github.com/ProgrammingBlockchain/ProgrammingBlockchainCodeExamples/) 60 | [成功者の殿堂](http://n.bitcoin.ninja/)(ここではこの本の中にあるチャレンジを完了できた人たちが一覧になっています。) 61 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [README](README.md) 4 | * [前書き](foreword.md) 5 | * [第2(コミュニティ)版](second_communitry_edition.md) 6 | * [イントロダクション](introduction/README.md) 7 | * [なぜ ビットコインプログラミングではなく、ブロックチェーンプログラミング ?](introduction/why_blockchain_programming_and_not_bitcoin_program.md) 8 | * [なぜ C\# か?](introduction/why_c.md) 9 | * [なぜこの本を読むべきか?](introduction/why_do_people_hate_bitcoin.md) 10 | * [この本へのクラウドファンディング](introduction/crowdfunding_this_book.md) 11 | * [参考文献](introduction/complementary_reading.md) 12 | * [図解について](introduction/diagrams.md) 13 | * [ライセンス:クリエイティブ・コモンズ \(ASA 3U\)](introduction/license_cc_asa_3u.md) 14 | * [前提事項](introduction/pre-requisites.md) 15 | * [プロジェクトのセットアップ](introduction/project_setup.md) 16 | * [ビットコインの移動](bitcoin_transfer/README.md) 17 | * [ビットコインアドレス](bitcoin_transfer/bitcoin_address.md) 18 | * [ScriptPubKey](bitcoin_transfer/payment_script.md) 19 | * [秘密鍵](bitcoin_transfer/private_key.md) 20 | * [トランザクション](bitcoin_transfer/transaction.md) 21 | * [ブロックチェーン](bitcoin_transfer/blockchain.md) 22 | * [“ブロックチェーンは、ビットコインを超えたもの”](bitcoin_transfer/the_blockchain_is_more_than_just_bitcoin.md) 23 | * [ビットコインを支払いに使う](bitcoin_transfer/spend_your_coin.md) 24 | * [個人認証として所有権の証明](bitcoin_transfer/proof_of_ownership_as_an_authentication_method.md) 25 | * [鍵生成と暗号化](key_generation/key_generation.md) 26 | * [それは十分にランダムだろうか?](key_generation/key_generation.md#is-it-random-enough) 27 | * [鍵導出関数](key_generation/key_generation.md#key-derivation-function) 28 | * [古き良き時代のように](key_generation/key_generation.md#like-the-good-ol-days) 29 | * [BIP38 \(パート2\)](key_generation/key_generation.md#bip38-part-2) 30 | * [HDウォレット \(BIP 32\)](key_generation/key_generation.md#hd-wallet-bip-32) 31 | * [HD鍵のためのネモニック\(記憶しやすい\)コード \(BIP39\)](key_generation/key_generation.md#mnemonic-code-for-hd-keys-bip39) 32 | * [ダークウォレット](key_generation/key_generation.md#dark-wallet) 33 | * [その他の所有権](other_types_of_ownership/README.md) 34 | * [P2PK\[H\] \(Pay to Public Key \[Hash\]\)](other_types_of_ownership/p2pk[h]_pay_to_public_key_[hash].md) 35 | * [P2WPKH \(Pay to Witness Public Key Hash\)](other_types_of_ownership/p2wpkh_pay_to_witness_public_key_hash.md) 36 | * [マルチシグ](other_types_of_ownership/multi_sig.md) 37 | * [P2SH \(Pay To Script Hash\)](other_types_of_ownership/p2sh_pay_to_script_hash.md) 38 | * [P2WSH \(Pay to Witness Script Hash\)](other_types_of_ownership/p2wsh_pay_to_witness_script_hash.md) 39 | * [P2W\* over P2SH](other_types_of_ownership/p2w_over_p2sh.md) 40 | * [任意性](other_types_of_ownership/arbitrary.md) 41 | * [TransactionBuilderを使ってみる](other_types_of_ownership/using_the_transactionbuilder.md) 42 | * [その他のアセットタイプ](other_types_of_asset/README.md) 43 | * [カラードコイン](other_types_of_asset/colored_coins.md) 44 | * [資産の発行](other_types_of_asset/issuing_an_asset.md) 45 | * [資産の移動](other_types_of_asset/transfer_an_asset.md) 46 | * [単体テスト](other_types_of_asset/unit_tests.md) 47 | * [リカーディアン・コントラクト](other_types_of_asset/ricardian_contracts.md) 48 | * [流動体民主主義](other_types_of_asset/liquid_democracy.md) 49 | * [Proof of Burn と評判](other_types_of_asset/proof_of_burn_and_reputation.md) 50 | * [秘密鍵を守る](security/protecting_your_private_keys.md) 51 | * [ケース・スタディ](implementations/README.md) 52 | * [HiddenWallet:鍵の管理\(HD ウォレット\)](implementations/hiddenbitcoinkey_storage_hd_wallet_md.md) 53 | 54 | -------------------------------------------------------------------------------- /assets/BitcoinAddress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/BitcoinAddress.png -------------------------------------------------------------------------------- /assets/BitcoinAddressToScriptPubKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/BitcoinAddressToScriptPubKey.png -------------------------------------------------------------------------------- /assets/BitcoinCoreTransaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/BitcoinCoreTransaction.png -------------------------------------------------------------------------------- /assets/BitcoinSecret.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/BitcoinSecret.png -------------------------------------------------------------------------------- /assets/BookQr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/BookQr.png -------------------------------------------------------------------------------- /assets/CeoMarketingAccounting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/CeoMarketingAccounting.png -------------------------------------------------------------------------------- /assets/Coinprism.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/Coinprism.png -------------------------------------------------------------------------------- /assets/Coinprism2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/Coinprism2.png -------------------------------------------------------------------------------- /assets/ColorMaker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ColorMaker.png -------------------------------------------------------------------------------- /assets/ColoredCoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ColoredCoin.png -------------------------------------------------------------------------------- /assets/ColoredTransaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ColoredTransaction.png -------------------------------------------------------------------------------- /assets/Derive1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/Derive1.png -------------------------------------------------------------------------------- /assets/Derive2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/Derive2.png -------------------------------------------------------------------------------- /assets/DeriveKeyPath.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/DeriveKeyPath.png -------------------------------------------------------------------------------- /assets/EncryptedKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/EncryptedKey.png -------------------------------------------------------------------------------- /assets/EncryptedKeyResult.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/EncryptedKeyResult.png -------------------------------------------------------------------------------- /assets/EphemKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/EphemKey.png -------------------------------------------------------------------------------- /assets/ExtKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ExtKey.png -------------------------------------------------------------------------------- /assets/ExtPubKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ExtPubKey.png -------------------------------------------------------------------------------- /assets/FetchColors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/FetchColors.png -------------------------------------------------------------------------------- /assets/FetchColors2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/FetchColors2.png -------------------------------------------------------------------------------- /assets/IColoredCoinTransactionRepository.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/IColoredCoinTransactionRepository.png -------------------------------------------------------------------------------- /assets/NicoWallet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/NicoWallet.png -------------------------------------------------------------------------------- /assets/NonHardened.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/NonHardened.png -------------------------------------------------------------------------------- /assets/OutPoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/OutPoint.png -------------------------------------------------------------------------------- /assets/PPKH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PPKH.png -------------------------------------------------------------------------------- /assets/PassphraseCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PassphraseCode.png -------------------------------------------------------------------------------- /assets/PassphraseCodeToEncryptedKeys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PassphraseCodeToEncryptedKeys.png -------------------------------------------------------------------------------- /assets/Power2Alice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/Power2Alice.png -------------------------------------------------------------------------------- /assets/PowerCoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PowerCoin.png -------------------------------------------------------------------------------- /assets/PowerCoin2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PowerCoin2.png -------------------------------------------------------------------------------- /assets/PowerCoin3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PowerCoin3.png -------------------------------------------------------------------------------- /assets/PowerCoin4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PowerCoin4.png -------------------------------------------------------------------------------- /assets/PowerCoin5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PowerCoin5.png -------------------------------------------------------------------------------- /assets/PrivKeyPubKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PrivKeyPubKey.png -------------------------------------------------------------------------------- /assets/PrivateKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PrivateKey.png -------------------------------------------------------------------------------- /assets/ProgrammingBlockchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ProgrammingBlockchain.png -------------------------------------------------------------------------------- /assets/PubKeyHashToBitcoinAddress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PubKeyHashToBitcoinAddress.png -------------------------------------------------------------------------------- /assets/PubKeyToAddr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PubKeyToAddr.png -------------------------------------------------------------------------------- /assets/PubKeyToScriptPubKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/PubKeyToScriptPubKey.png -------------------------------------------------------------------------------- /assets/QBitNuGet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/QBitNuGet.png -------------------------------------------------------------------------------- /assets/RawTx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/RawTx.png -------------------------------------------------------------------------------- /assets/ReceiverStealth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ReceiverStealth.png -------------------------------------------------------------------------------- /assets/RedeemScript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/RedeemScript.png -------------------------------------------------------------------------------- /assets/RootKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/RootKey.png -------------------------------------------------------------------------------- /assets/ScannerRecover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ScannerRecover.png -------------------------------------------------------------------------------- /assets/ScriptCoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ScriptCoin.png -------------------------------------------------------------------------------- /assets/ScriptCoinFromCoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ScriptCoinFromCoin.png -------------------------------------------------------------------------------- /assets/ScriptPubKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ScriptPubKey.png -------------------------------------------------------------------------------- /assets/SignedTransaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/SignedTransaction.png -------------------------------------------------------------------------------- /assets/SpendTx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/SpendTx.png -------------------------------------------------------------------------------- /assets/StealthAddress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/StealthAddress.png -------------------------------------------------------------------------------- /assets/StealthCoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/StealthCoin.png -------------------------------------------------------------------------------- /assets/StealthMetadata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/StealthMetadata.png -------------------------------------------------------------------------------- /assets/ThirdPartyKeyGeneration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ThirdPartyKeyGeneration.png -------------------------------------------------------------------------------- /assets/TransactionBuilder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/TransactionBuilder.png -------------------------------------------------------------------------------- /assets/TransparentWallet2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/TransparentWallet2.png -------------------------------------------------------------------------------- /assets/Trezor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/Trezor.png -------------------------------------------------------------------------------- /assets/TxIn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/TxIn.png -------------------------------------------------------------------------------- /assets/TxOut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/TxOut.png -------------------------------------------------------------------------------- /assets/Visio/BIP32.vsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/Visio/BIP32.vsd -------------------------------------------------------------------------------- /assets/aliceSigned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/aliceSigned.png -------------------------------------------------------------------------------- /assets/bitcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/bitcoin.png -------------------------------------------------------------------------------- /assets/bobSigned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/bobSigned.png -------------------------------------------------------------------------------- /assets/ccasa3u.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/ccasa3u.png -------------------------------------------------------------------------------- /assets/coin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/coin.png -------------------------------------------------------------------------------- /assets/encrypted_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/encrypted_key.png -------------------------------------------------------------------------------- /assets/fullySigned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/fullySigned.png -------------------------------------------------------------------------------- /assets/nuget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/nuget.png -------------------------------------------------------------------------------- /assets/nuget_jp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/nuget_jp.png -------------------------------------------------------------------------------- /assets/segwit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/segwit.png -------------------------------------------------------------------------------- /assets/visualstudio_enablesourceserversupport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/visualstudio_enablesourceserversupport.png -------------------------------------------------------------------------------- /assets/visualstudio_enablesourceserversupport_jp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/assets/visualstudio_enablesourceserversupport_jp.png -------------------------------------------------------------------------------- /bitcoin_transfer/README.md: -------------------------------------------------------------------------------- 1 | # ビットコインの移動 {#bitcoin-transfer} 2 | 3 | ビットコインでは、確実にトランザクションを正しく処理するように、全てのことが設計されている。この章では「手動で」シンプルなビットコインのトランザクションを生成することを通して、基本的なビットコインの概略を紹介する。 4 | 5 | その後、トランザクションを生成するための、より高いレベルのフレームワークを紹介する。 6 | -------------------------------------------------------------------------------- /bitcoin_transfer/bitcoin_address.md: -------------------------------------------------------------------------------- 1 | ## ビットコインアドレス {#bitcoin-address} 2 | 3 | **ビットコインアドレス**が、支払いを受けるために公開するものであることは知ってのとおりだ。 4 | 5 | ![](../assets/BitcoinAddress.png) 6 | 7 | あなたがこのアドレス宛てにもらったビットコインを使うには、ウォレットで**秘密鍵**を使うということも、おそらく知っているだろう。 8 | ![](../assets/PrivateKey.png) 9 | 10 | 秘密鍵はネットワークには保管されず、インターネットにアクセスすることなく生成することができる。 11 | 12 | 秘密鍵を生成してみよう。 13 | 14 | ```cs 15 | Key privateKey = new Key(); // ランダムな秘密鍵を生成 16 | ``` 17 | 18 | 秘密鍵から**公開鍵**を作成する。これは一方向性の暗号学的な機能を使っていて、逆に公開鍵から秘密鍵は作れない。 19 | 20 | ![](../assets/PrivKeyPubKey.png) 21 | 22 | ```cs 23 | PubKey publicKey = privateKey.PubKey; 24 | Console.WriteLine(publicKey); // 0251036303164f6c458e9f7abecb4e55e5ce9ec2b2f1d06d633c9653a07976560c 25 | ``` 26 | 27 | ビットコインには2つの**ネットワーク**がある。 28 | 29 | * **TestNet** は開発を目的としたビットコインのネットワーク。このネットワーク上のビットコインに価値はない。 30 | * **MainNet** は普通のユーザーが使うネットワークである。 31 | 32 | > 注釈:TestNetのコインは**faucets(蛇口)**サイトを使うことですぐに手に入る。「get testnet bitcoins」で検索してほしい。 33 | 34 | 公開鍵とアドレスを使用するネットワークの種類から、ビットコインアドレスを簡単に作ることができる。 35 | 36 | ![](../assets/PubKeyToAddr.png) 37 | 38 | ```cs 39 | Console.WriteLine(publicKey.GetAddress(Network.Main)); // 1PUYsjwfNmX64wS368ZR5FMouTtUmvtmTY 40 | Console.WriteLine(publicKey.GetAddress(Network.TestNet)); // n3zWAo2eBnxLr3ueohXnuAa8mTVBhxmPhq 41 | ``` 42 | 43 | **正確に言うと、ビットコインアドレスはバージョンを示す先頭1バイト(TestNetかMainNetかで異なる)と公開鍵ハッシュで構成されており、それらが結合された後、Base58Checkにエンコードされる。** 44 | 45 | ![](../assets/PubKeyHashToBitcoinAddress.png) 46 | 47 | ```cs 48 | var publicKeyHash = publicKey.Hash; 49 | Console.WriteLine(publicKeyHash); // f6889b21b5540353a29ed18c45ea0031280c42cf 50 | var mainNetAddress = publicKeyHash.GetAddress(Network.Main); 51 | var testNetAddress = publicKeyHash.GetAddress(Network.TestNet); 52 | ``` 53 | 54 | > 注釈:公開鍵ハッシュは、まず公開鍵をSHA256でハッシュ化し、その結果に対してRIPEMD160でさらにハッシュ化してビッグエンディアンで並べている。プログラミング関数なら、「RIPEMD160\(SHA256\(pubkey\)\)」のように表せるだろう。 55 | 56 | Base58Checkエンコーディングには誤字を防止するためのチェックサムがあったり、「0(ゼロ)」や「O(オー)」のようにどちらとも見える文字を使わないようにするという気の利いた機能がある。 57 | Base58Checkエンコードされたビットコインアドレスは、ウォレットを使っているユーザーが、間違えて意図していないネットワークにビットコインを確実に送らないようにする。 58 | 59 | ```cs 60 | Console.WriteLine(mainNetAddress); // 1PUYsjwfNmX64wS368ZR5FMouTtUmvtmTY 61 | Console.WriteLine(testNetAddress); // n3zWAo2eBnxLr3ueohXnuAa8mTVBhxmPhq 62 | ``` 63 | 64 | > 参考:MainNetでビットコイン プログラミングを練習すると、もし失敗したらそれはきっと忘れられないものになるだろう。 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /bitcoin_transfer/blockchain.md: -------------------------------------------------------------------------------- 1 | ## ブロックチェーン {#blockchain} 2 | 3 | 使われたトランザクションアウトプットの所有権を証明した一方で、そのトランザクションアウトプットがたしかに存在しているかどうかは証明していないことに、ひょっとすると気づいているかもしれない。実はこここそが、ブロックチェーンの主機能が秀でるところである。 4 | 5 | ブロックチェーンは、ジェネシスブロックとして知られている最初のビットコインのトランザクションが発生して以降の、すべてのトランザクションのデータベースとなっている。そしてブロックチェーンは世界中に複製されている。もしビットコインコアを使っているなら、あなたのコンピューターにもブロックチェーンの最初から最後までが保存される。一度トランザクションがブロックチェーン上に表れたら、その存在を証明するのはとても簡単なのだ。 6 | 7 | **マイナー** は、ビットコインブロックチェーンにトランザクションを記録することだけがゴールである。しかしマイナーはトランザクションを1つ受け取るたびにビットコインブロックチェーンを変更しているわけではない。そうではなく、それぞれのマイナーは、**ブロック** と呼ばれる同時期に発生したトランザクションの集まりをブロックチェーンに追加しようとする。ネットワーク上にある他のノードは、その新しいブロックがビットコインプロトコルに示されているルールに従っているかを確認する。もし2人のマイナーが同時にブロックに加えたら、**フォーク** が生まれ、しかし結局は最もマイニング**労力(work)** が費やされたフォークだけが生き残る。もしマイナーがブロックに無効なトランザクションを含めようとしたら、他のノードがそれを承認しないので、そのマイナーはブロックを作るために使われた投資を無駄にすることになる。 8 | 9 | あるマイナーが有効なブロックを送信できたら、そのブロックに含まれているすべてのトランザクションが **Confirmed(承認済)** となったと認識される。このときすべてのマイナーはその時点で取り組んでいるマイニング作業を破棄して、新しいトランザクションをブロックに含める作業を始めなければならない。ブロックが承認されると、ビットコインブロックチェーンにそれが書き込まれ、その後他のブロックがどんどん追加される度に、そのブロックの承認が取り消される可能性は劇的に下がる。 10 | 11 | 歴史の中で初めて、私たちは簡単に書き換えられず、信用の必要性を排除し、検閲ができない、そして、広く分散化されたデータベースを手にした。ブロックチェーンを台帳にたとえるのは、ビットコインを通貨として考えるときにだけ妥当な話である。 12 | 13 | ビットコインブロックチェーンはデータベースで、だれでもそのデータに好きな意味を持たせることができる。すぐに気づくだろうが、ビットコインのトランザクションはただのビットコインの移動だけではなく、より多くの情報を持つことができる。ビットコインのトランザクションデータと消すのが不可能なデータベースの中の1レコードといえる。 14 | 15 | ユーザーとして、2つの方法でブロックチェーンの中にある特定のトランザクションの存在を確認することができる。 16 | 17 | * ブロックチェーン全体から探す。ブロックチェーンは、本書を書いている時点で数十ギガバイトのサイズだ。 18 | * 数キロバイトの部分的なマークルツリーを探索する。マークルツリーについては Simple Payment Verificationと関連するので、後で、解説する。 19 | -------------------------------------------------------------------------------- /bitcoin_transfer/payment_script.md: -------------------------------------------------------------------------------- 1 | ## ScriptPubKey {#payment-script} 2 | 3 | ひょっとすると知らないかもしれないが、実は、ビットコインのブロックチェーンの内部には、ビットコインアドレスなどというものはない。内部的に、ビットコインのプロトコルでは、ビットコインを受け取る相手を**ScriptPubKey**で認識することになっている。 4 | 5 | ![](../assets/ScriptPubKey.png) 6 | **ScriptPubKey**は、例えば、このように表現される。 7 | `OP_DUP OP_HASH160 14836dbe7f38c5ac3d49e8d790af808a4ee9edcf OP_EQUALVERIFY OP_CHECKSIG` 8 | 9 | この短いスクリプトこそ、ビットコインの所有権を主張するために、どんな条件が揃わなければならないかを説明するものだ。この本のレッスンを進めていく中で、**ScriptPubKey**の中にある命令をいくつか見ることになる。 10 | 11 | ScriptPubKeyはビットコインアドレスから生成することができる。これはすべてのビットコインのクライアントが、「人間の目に易しい」ビットコインアドレスから、ブロックチェーンが理解できるアドレスへ変換するために行っているステップの1つである。 12 | 13 | ![](../assets/BitcoinAddressToScriptPubKey.png) 14 | 15 | ```cs 16 | var publicKeyHash = new KeyId("14836dbe7f38c5ac3d49e8d790af808a4ee9edcf"); 17 | 18 | var testNetAddress = publicKeyHash.GetAddress(Network.TestNet); 19 | var mainNetAddress = publicKeyHash.GetAddress(Network.Main); 20 | 21 | Console.WriteLine(mainNetAddress.ScriptPubKey); // OP_DUP OP_HASH160 14836dbe7f38c5ac3d49e8d790af808a4ee9edcf OP_EQUALVERIFY OP_CHECKSIG 22 | Console.WriteLine(testNetAddress.ScriptPubKey); // OP_DUP OP_HASH160 14836dbe7f38c5ac3d49e8d790af808a4ee9edcf OP_EQUALVERIFY OP_CHECKSIG 23 | ``` 24 | 25 | TestNetの**ScriptPubKey**とMainNetの**ScriptPubKey**が同じになっているのに気づいただろうか? 26 | そして、**ScriptPubKey**には公開鍵ハッシュが含まれているのに気づいただろうか? 27 | この時点ではまだ詳細には触れないでおく。しかし、ScriptPubKeyはビットコインアドレスと全く関係がないように見えるが、公開鍵ハッシュを持っているのだ。 28 | 29 | ビットコインアドレスはそのアドレスが使われるネットワークを指し示す1バイトのバージョンバイトと公開鍵のハッシュ値で構成されている。だから**ScriptPubKey**の情報とネットワークを指し示す情報からビットコインアドレスに戻すことができる。 30 | 31 | ```cs 32 | var paymentScript = publicKeyHash.ScriptPubKey; 33 | var sameMainNetAddress = paymentScript.GetDestinationAddress(Network.Main); 34 | Console.WriteLine(mainNetAddress == sameMainNetAddress); // True 35 | ``` 36 | 37 | または**ScriptPubKey**から公開鍵ハッシュに戻し、さらにそれからビットコインアドレスを生成することができる。 38 | 39 | ```cs 40 | var samePublicKeyHash = (KeyId) paymentScript.GetDestination(); 41 | Console.WriteLine(publicKeyHash == samePublicKeyHash); // True 42 | var sameMainNetAddress2 = new BitcoinPubKeyAddress(samePublicKeyHash, Network.Main); 43 | Console.WriteLine(mainNetAddress == sameMainNetAddress2); // True 44 | ``` 45 | 46 | > 注釈:ScriptPubKeyには必ずしもビットコインを使う事ができる公開鍵ハッシュを含む必要があるというわけではなく、別の種類のスクリプトを入れてもよい。 47 | 48 | さてここまでで、秘密鍵、公開鍵、公開鍵ハッシュ、ビットコインアドレスとScriptPubKeyの関係性を理解したと思う。 49 | 50 | 次の章からは基本的にScriptPubKeyだけを使う。ビットコインアドレスはユーザーインターフェースの発想から使われるものだからだ。 51 | 52 | -------------------------------------------------------------------------------- /bitcoin_transfer/private_key.md: -------------------------------------------------------------------------------- 1 | ## 秘密鍵 {#private-key} 2 | 3 | 秘密鍵はよく、ビットコインアドレスと同じBase58Check形式の、**ビットコインシークレット**で表現される。これはウォレットにインポートするフォーマット(**Wallet Import Format, WIF**)としても知られている。 4 | 5 | ![](../assets/BitcoinSecret.png) 6 | 7 | ```cs 8 | Key privateKey = new Key(); // ランダムな秘密鍵の生成 9 | BitcoinSecret mainNetPrivateKey = privateKey.GetBitcoinSecret(Network.Main); // メインネット用のビットコインシークレットを取得 10 | BitcoinSecret testNetPrivateKey = privateKey.GetBitcoinSecret(Network.TestNet); // テストネット用のビットコインシークレットを取得 11 | Console.WriteLine(mainNetPrivateKey); // L5B67zvrndS5c71EjkrTJZ99UaoVbMUAK58GKdQUfYCpAa6jypvn 12 | Console.WriteLine(testNetPrivateKey); // cVY5auviDh8LmYUW8AfafseD6p6uFoZrP7GjS3rzAerpRKE9Wmuz 13 | 14 | bool WifIsBitcoinSecret = mainNetPrivateKey == privateKey.GetWif(Network.Main); 15 | Console.WriteLine(WifIsBitcoinSecret); // 正 16 | ``` 17 | 18 | 注目してほしいのだが、**ビットコインシークレット** から **秘密鍵** を導出するのは簡単だ。一方で、ビットコインアドレスから公開鍵を導くことはできない。なぜならば、ビットコインアドレスは公開鍵のハッシュを含んでいるのであって、公開鍵自体を含んではないからだ。 19 | 次の2つのコードブロックの比較することで、上記の違いを理解してみよう。 20 | 21 | ```cs 22 | Key privateKey = new Key(); // ランダムな秘密鍵の生成 23 | BitcoinSecret bitcoinSecret = privateKey.GetWif(Network.Main); // L5B67zvrndS5c71EjkrTJZ99UaoVbMUAK58GKdQUfYCpAa6jypvn 24 | Key samePrivateKey = bitcoinSecret.PrivateKey; 25 | Console.WriteLine(samePrivateKey == privateKey); // 正 26 | ``` 27 | 28 | ```cs 29 | PubKey publicKey = privateKey.PubKey; 30 | BitcoinPubKeyAddress bitcoinPubicKey = publicKey.GetAddress(Network.Main); // 1PUYsjwfNmX64wS368ZR5FMouTtUmvtmTY 31 | //PubKey samePublicKey = bitcoinPubicKey.ItIsNotPossible;// 戻すのは不可能 32 | ``` 33 | 34 | ### 練習 : 35 | 36 | 1. MainNet向けの秘密鍵を生成し、それをメモする。 37 | 2. 秘密鍵からビットコインアドレスを生成する。 38 | 3. そのビットコインアドレスにビットコインを送る。無くすには惜しいくらいの額を送金すれば、次のレッスンでそれらを取り戻すために集中し、モチベーションを持続できるだろう。 39 | -------------------------------------------------------------------------------- /bitcoin_transfer/proof_of_ownership_as_an_authentication_method.md: -------------------------------------------------------------------------------- 1 | ## 所有権の証明による個人の認証 {#proof-of-ownership-as-an-authentication-method} 2 | 3 | > \[[2016.05.02](https://www.youtube.com/watch?v=dZNtbAFnr-0)\] 私の名前はクレイグ・ライトだ。これからビットコインで最初に作成されたトランザクションに関連付けられた公開鍵を使ってメッセージに署名することをデモンストレーションしよう。 4 | 5 | ```cs 6 | var bitcoinPrivateKey = new BitcoinSecret("XXXXXXXXXXXXXXXXXXXXXXXXXX"); 7 | 8 | var message = "I am Craig Wright"; 9 | string signature = bitcoinPrivateKey.PrivateKey.SignMessage(message); 10 | Console.WriteLine(signature); // IN5v9+3HGW1q71OqQ1boSZTm0/DCiMpI8E4JB1nD67TCbIVMRk/e3KrTT9GvOuu3NGN0w8R2lWOV2cxnBp+Of8c= 11 | ``` 12 | 13 | これはそんなに難しいことだろうか? 14 | 15 | クレイグ・ライトという人物を覚えているかもしれない。彼は自分がサトシ・ナカモトであると,是非とも信じてほしいと思っていた人物だ。 16 | 彼はあるソーシャルエンジニアリングの方法を使って、一握りの影響力のあるビットコイン業界の人物やジャーナリストを納得させることに成功した。 17 | しかし、幸運なことにデジタル署名に関しては、そんなふうにうまくいかない。 18 | ジェネシスブロックにある、最初のビットコイントランザクションのアドレスを[インターネット](https://en.bitcoin.it/wiki/Genesis_block)でさっと見てみよう。[1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa](https://blockchain.info/address/1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa) とある。さあ彼の主張を確かめてみよう。 19 | 20 | ```cs 21 | var message = "I am Craig Wright"; 22 | var signature = "IN5v9+3HGW1q71OqQ1boSZTm0/DCiMpI8E4JB1nD67TCbIVMRk/e3KrTT9GvOuu3NGN0w8R2lWOV2cxnBp+Of8c="; 23 | 24 | var address = new BitcoinPubKeyAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"); 25 | bool isCraigWrightSatoshi = address.VerifyMessage(message, signature); 26 | 27 | Console.WriteLine("Is Craig Wright Satoshi? " + isCraigWrightSatoshi); 28 | ``` 29 | 30 | ネタバレ注意!結果のブーリアンの値はfalseになるだろう。 31 | 32 | ここにコインを移動させないで、どうやって特定のアドレスを自分のものだと証明できるかの方法を示そう。 33 | 34 | **ビットコインアドレス:** 35 | [1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB](https://blockchain.info/address/1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB) 36 | **メッセージ:** 37 | Nicolas Dorier Book Funding Address 38 | **署名:** 39 | H1jiXPzun3rXi0N9v9R5fAWrfEae9WPmlL5DJBj1eTStSvpKdRR8Io6/uT9tGH/3OnzG6ym5yytuWoA9ahkC3dQ= 40 | 41 | これらの情報でNicolas Dorierがこの本の秘密鍵を所有していることの証明ができる。 42 | **Exercise:**Nicolas先生がうそをついていないことを確かめてみよう! 43 | 44 | ### 追記 45 | 46 | PGPがどのように動いているか知っているだろうか?ビットコインブロックチェーンととてもよく似ていないだろうか? 47 | たぶんビットコインブロックチェーンはよりユーザーフレンドリーな、PGPの代わりとしての基盤となり得るだろう。 48 | どうかNBitcoinでそれを作って欲しい。:-\) 49 | -------------------------------------------------------------------------------- /bitcoin_transfer/spend_your_coin.md: -------------------------------------------------------------------------------- 1 | ## ビットコインを使ってみる {#spend-your-coin} 2 | 3 | さあ今や **ビットコインアドレス**、**ScriptPubKey**、**秘密鍵**や**マイナー** とは何かがわかったので、自分の手で初めての**トランザクション**を作れるだろう。 4 | 5 | このレッスンを進めて1行ごとにコードを追加していくと、最終的にTwitterライクなメッセージで、この本へのフィードバックを残すプログラムを作るようになっている。 6 | 7 | では前のレッスンでやったように、消費したい **トランザクションアウトプット** を含む **トランザクション** を見てみよう。 8 | 9 | 新しい **コンソールプロジェクト**(.NET4.5以上)を作り、**QBitNinja.Client** のNuGetパッケージをインストールしてほしい。 10 | 11 | すでに秘密鍵を作成して、メモを取っただろうか?そして、その鍵に対応するビットコインアドレスを取得して、ビットコインを送金しただろうか?もしまだやってなくても心配しないでいい。どうやってやるかここで簡単に繰り返そう。 12 | 13 | ```cs 14 | var network = Network.Main; 15 | 16 | var privateKey = new Key(); 17 | var bitcoinPrivateKey = privateKey.GetWif(network); 18 | var address = bitcoinPrivateKey.GetAddress(); 19 | 20 | Console.WriteLine(bitcoinPrivateKey); 21 | Console.WriteLine(address); 22 | ``` 23 | 24 | **bitcoinPrivateKey** と **address** の値をメモし、そこにいくらかのコインを送り、そのトランザクションIDをメモしてくれ。(トランザクションIDは、自分のウォレットアプリに(多分)表示される、それか、[blockchain.info](https://blockchain.info/)のようなブロックエクスプローラーで(アドレスから)見つけることができる。) 25 | 26 | 次に、秘密鍵をインポートする。 27 | 28 | ```cs 29 | var bitcoinPrivateKey = new 30 | BitcoinSecret("cSZjE4aJNPpBtU6xvJ6J4iBzDgTmzTjbq8w2kqnYvAprBCyTsG4x"); 31 | var network = bitcoinPrivateKey.Network; 32 | var address = bitcoinPrivateKey.GetAddress(); 33 | 34 | Console.WriteLine(network); // TestNet 35 | Console.WriteLine(address); // mzK6Jy5mer3ABBxfHdcxXEChsn3mkv8qJv 36 | ``` 37 | 38 | そして最後にトランザクションの情報を取得する。 39 | 40 | ```cs 41 | var client = new QBitNinjaClient(network); 42 | var transactionId = uint256.Parse("e44587cf08b4f03b0e8b4ae7562217796ec47b8c91666681d71329b764add2e3"); 43 | var transactionResponse = client.GetTransaction(transactionId).Result; 44 | 45 | Console.WriteLine(transactionResponse.TransactionId); // e44587cf08b4f03b0e8b4ae7562217796ec47b8c91666681d71329b764add2e3 46 | Console.WriteLine(transactionResponse.Block.Confirmations); 47 | ``` 48 | 49 | さあ、これでトランザクションを生成する情報はすべて揃った。で、必要な質問はこれだ。「**どこから、どこへ、いくら?**」 50 | 51 | ### どこから? 52 | 53 | このケースでは、前のトランザクションの2番目のoutpointを使いたいのだが、どのようにそれを見つけたのかを示す。 54 | 55 | ```cs 56 | var receivedCoins = transactionResponse.ReceivedCoins; 57 | OutPoint outPointToSpend = null; 58 | foreach (var coin in receivedCoins) 59 | { 60 | if (coin.TxOut.ScriptPubKey == bitcoinPrivateKey.ScriptPubKey) 61 | { 62 | outPointToSpend = coin.Outpoint; 63 | } 64 | } 65 | if(outPointToSpend == null) 66 | throw new Exception("エラー:どのトランザクションアウトプットも送ったコインのScriptPubKeyを持ってない!"); 67 | Console.WriteLine("{0}番目のアウトポイントを使いたい。", outPointToSpend.N + 1); 68 | ``` 69 | 70 | 支払いのためにはトランザクションの中でこのoutpointを参照する必要がある。以下のようにトランザクションを生成する。 71 | 72 | ```cs 73 | var transaction = new Transaction(); 74 | transaction.Inputs.Add(new TxIn() 75 | { 76 | PrevOut = outPointToSpend 77 | }); 78 | ``` 79 | 80 | ### どこへ? 81 | 82 | 必要な質問は覚えているだろうか?「**どこから、どこへ、いくら?**」だ。 83 | **トランザクションインプット** を組み立ててトランザクションに加えることが、「どこから?」という質問への答えだった。 84 | **トランザクションアウトプット** を組み立ててトランザクションに加えることは、残っている2つの質問への答えである。 85 | 86 | この本への寄付アドレス:[1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB](https://blockchain.info/address/1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB) 87 | 寄付されたお金は本の残りを書いている間、私が食事できて素直にいられるように使う「コーヒー&寿司ウォレット」という名前の僕のウォレットに入る。 88 | もしこのチャレンジに成功すると、[http://n.bitcoin.ninja/](http://n.bitcoin.ninja/)の **成功者の殿堂リスト** の中に自分の寄付を見つけることができるだろう(気前の良さ順に表示される)。 89 | 90 | ```cs 91 | var hallOfTheMakersAddress = new BitcoinPubKeyAddress("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB"); 92 | ``` 93 | 94 | もしTestNet上でコードを動かしているなら、どのTestNetのアドレスにでも良いのでコインを送ってみよう。 95 | 96 | ```cs 97 | var hallOfTheMakersAddress = BitcoinAddress.Create("mzp4No5cmCXjZUpf112B1XWsvWBfws5bbB"); 98 | ``` 99 | 100 | ### いくら? 101 | 102 | もし **1BTC** を伴う **トランザクションインプット** から **0.5BTC** を使いたいとしても、確実にすべてのコインを使い切らなければならない! 103 | 図解が以下に示すとおり、**トランザクションアウトプット** が **0.5** BTCを成功者の殿堂に、そしてあなたに**0.4999**BTCを戻すように仕分けている。 104 | 残りの **0.0001BTC** はどうなったのだろう?これはマイナーの手数料となっていて、彼らがこのトランザクションを次のブロックに含めるためのインセンティブとなっているのであった。 105 | 106 | ![](../assets/SpendTx.png) 107 | 108 | ```cs 109 | // 成功者の殿堂に送る分 110 | TxOut hallOfTheMakersTxOut = new TxOut() 111 | { 112 | Value = new Money((decimal)0.5, MoneyUnit.BTC), 113 | ScriptPubKey = hallOfTheMakersAddress.ScriptPubKey 114 | }; 115 | 116 | // 自分に戻す分 (おつり) 117 | TxOut changeBackTxOut = new TxOut() 118 | { 119 | Value = new Money((decimal)0.4999, MoneyUnit.BTC), 120 | ScriptPubKey = bitcoinPrivateKey.ScriptPubKey 121 | }; 122 | 123 | transaction.Outputs.Add(hallOfTheMakersTxOut); 124 | transaction.Outputs.Add(changeBackTxOut); 125 | ``` 126 | 127 | *訳注:自分に戻す分 (おつり)がゼロの場合は、その TxOut (上記では changeBackTxOut) をトランザクションに追加する必要はない。数量がゼロのTxOutはトランザクション実行時にエラーとなる。* 128 | 129 | ここでコードの微調整をしてみる。 130 | 以下のリンクから、この章のサンプルコードで使っているビットコインアドレスをブロックエクスプローラーでチェックできる。(TestNetのアドレスを使っているが。) 131 | 132 | [http://tbtc.blockr.io/address/info/mzK6Jy5mer3ABBxfHdcxXEChsn3mkv8qJv](http://tbtc.blockr.io/address/info/mzK6Jy5mer3ABBxfHdcxXEChsn3mkv8qJv) 133 | 134 | ```cs 135 | // ビットコインをいくら送金先に送りたいか 136 | var hallOfTheMakersAmount = new Money(0.5m, MoneyUnit.BTC); 137 | /* これを書いている時点では、マイニング手数料は5セント 138 | * だが、ビットコインのマーケット価格と 139 | * その時の推奨手数料レートに合わせて 140 | * 手数料を上げるか、もしくは、下げるかを考慮する必要がある。 141 | */ 142 | var minerFee = new Money(0.0001m, MoneyUnit.BTC); 143 | // UTXOからいくらトータルでビットコインを 使いたいか。 144 | var txInAmount = receivedCoins[(int) outPointToSpend.N].TxOut.Value; 145 | Money changeBackAmount = txInAmount - hallOfTheMakersAmount - minerFee; 146 | ``` 147 | 148 | 計算した値をトランザクションアウトプットに追加する。 149 | 150 | ```cs 151 | TxOut hallOfTheMakersTxOut = new TxOut() 152 | { 153 | Value = hallOfTheMakersAmount, 154 | ScriptPubKey = hallOfTheMakersAddress.ScriptPubKey 155 | }; 156 | 157 | TxOut changeBackTxOut = new TxOut() 158 | { 159 | Value = changeBackAmount, 160 | ScriptPubKey = bitcoinPrivateKey.ScriptPubKey 161 | }; 162 | ``` 163 | 164 | そしてそれらをトランザクションに追加する。 165 | 166 | ```cs 167 | transaction.Outputs.Add(hallOfTheMakersTxOut); 168 | transaction.Outputs.Add(changeBackTxOut); 169 | ``` 170 | 171 | ### ブロックチェーン上でのメッセージ送信 172 | 173 | さあ、フィードバックを追加しよう!フィードバックは40バイト以下でなければならない。そうでないとアプリケーションがクラッシュする。 174 | このフィードバックはトランザクションと一緒に、(トランザクションが承認された後に)[成功者の殿堂](http://n.bitcoin.ninja/)の中に現れる。 175 | 176 | ```cs 177 | var message = "nopara73 loves NBitcoin!"; 178 | var bytes = Encoding.UTF8.GetBytes(message); 179 | transaction.Outputs.Add(new TxOut() 180 | { 181 | Value = Money.Zero, 182 | ScriptPubKey = TxNullDataTemplate.Instance.GenerateScriptPubKey(bytes) 183 | }); 184 | ``` 185 | 186 | 署名する前に、ここまでをまとめるため、トランザクション全体を見てほしい。 187 | 3つの**トランザクションアウトプット**があり、2つは**コイン付き**で、1つは**コインなし**(メッセージあり)となっている。そこで、「普通の」**トランザクションアウトプット** の **ScriptPubKey** とメッセージ付きの **トランザクションアウトプット** の **ScriptPubKey** の違いに気づくだろう。 188 | 189 | ```json 190 | { 191 | "hash": "b7803df4b90fd615532bcbdb3b63eb1af5a2e4ae36f29a6fbf9f57d0a1842e0a", 192 | "ver": 1, 193 | "vin_sz": 1, 194 | "vout_sz": 3, 195 | "lock_time": 0, 196 | "size": 154, 197 | "in": [ 198 | { 199 | "prev_out": { 200 | "hash": "e44587cf08b4f03b0e8b4ae7562217796ec47b8c91666681d71329b764add2e3", 201 | "n": 1 202 | }, 203 | "scriptSig": "" 204 | } 205 | ], 206 | "out": [ 207 | { 208 | "value": "0.50000000", 209 | "scriptPubKey": "OP_DUP OP_HASH160 d3a689bc36464b9d74e1721fd321d4686eae594e OP_EQUALVERIFYOP_CHECKSIG" 210 | }, 211 | { 212 | "value": "0.62840112", 213 | "scriptPubKey": "OP_DUP OP_HASH160 ce2c16edb74aef1caa6db0078af9d3a5b8fd12d1 OP_EQUALVERIFYOP_CHECKSIG" 214 | }, 215 | { 216 | "value": "0.00000000", 217 | "scriptPubKey": "OP_RETURN 6e6f706172613733206c6f766573204e426974636f696e21" 218 | } 219 | ] 220 | } 221 | ``` 222 | 223 | **トランザクションインプット**により着目してほしい。そこには **prev\_out**と**scriptSig**がある。 224 | **Exercise**:読み進む前に、このコードの中で **scriptSig** に何を入れるのか、そして、どのようにそれをコーディングして取得できるかを考えてみよう! 225 | 226 | ブロックエクスプローラーで、**prev\_out**の**ハッシュ**をチェックしてみよう。 227 | 228 | [http://tbtc.blockr.io/tx/info/e44587cf08b4f03b0e8b4ae7562217796ec47b8c91666681d71329b764add2e3](http://tbtc.blockr.io/tx/info/e44587cf08b4f03b0e8b4ae7562217796ec47b8c91666681d71329b764add2e3) 229 | ここで**prev\_out**のnの値\(インデックス\)は1だ。インデックスは0から始まるから、トランザクションの2番目のアウトプットを使いたいということになる。 230 | ブロックエクスプローラーの中で該当するアドレスが`mzK6Jy5mer3ABBxfHdcxXEChsn3mkv8qJv`であるとわかるので、このようにアドレスからscriptSigが得られる。 231 | 232 | ```cs 233 | var address = BitcoinAddress.Create("mzK6Jy5mer3ABBxfHdcxXEChsn3mkv8qJv"); 234 | transaction.Inputs[0].ScriptSig = address.ScriptPubKey; 235 | ``` 236 | 237 | ### トランザクションに署名する 238 | 239 | さあトランザクションを作成したので、署名しなければならない。言い換えれば、私たちはトランザクションインプットの中で参照した前トランザクションのアウトプットが自分のものであると証明しなければならないのだ。 240 | 241 | 署名は[複雑](https://en.bitcoin.it/w/images/en/7/70/Bitcoin_OpCheckSig_InDetail.png)だと思われるかもしれないが、我々がそれを簡単にしよう。 242 | 243 | 最初に**scriptSig**に**入れた値**から、どのようにそれを得たかをコードから振り返ってみよう。思い出してほしい、ブロックエクスプローラーから上記のアドレスをコピー&ペーストしただろうが、今度はビットコインシークレットから取得してみよう。 244 | 245 | ```cs 246 | transaction.Inputs[0].ScriptSig = bitcoinPrivateKey.ScriptPubKey; 247 | ``` 248 | 249 | そして秘密鍵を署名のためにパラメーターとして与える必要がある。 250 | 251 | ```cs 252 | transaction.Sign(bitcoinPrivateKey, false); 253 | ``` 254 | 255 | ### トランザクションを伝搬させる 256 | 257 | これで君の最初のトランザクションに署名したのだ。おめでとう!トランザクションはもうその役目を果たす準備ができている。残るはマイナーがそのトランザクションを把握できるようにネットワークに伝搬させるだけだ。 258 | 259 | #### QBitNinjaを使って: 260 | 261 | ```cs 262 | BroadcastResponse broadcastResponse = client.Broadcast(transaction).Result; 263 | 264 | if (!broadcastResponse.Success) 265 | { 266 | Console.WriteLine("ErrorCode: " + broadcastResponse.Error.ErrorCode); 267 | Console.WriteLine("Error message: " + broadcastResponse.Error.Reason); 268 | } 269 | else 270 | { 271 | Console.WriteLine("Success! You can check out the hash of the transaciton in any block explorer:"); 272 | Console.WriteLine(transaction.GetHash()); 273 | } 274 | ``` 275 | 276 | #### ローカルにインストールされているBitcoin Coreを使って: 277 | 278 | ```cs 279 | using (var node = Node.ConnectToLocal(network)) //Connect to the node 280 | { 281 | node.VersionHandshake(); //Say hello 282 | //Advertize your transaction (send just the hash) 283 | node.SendMessage(new InvPayload(InventoryType.MSG_TX, transaction.GetHash())); 284 | //Send it 285 | node.SendMessage(new TxPayload(transaction)); 286 | Thread.Sleep(500); //Wait a bit 287 | } 288 | ``` 289 | 290 | ここでは_using\*_コードブロックで、ノードとのコネクションを閉じる処理をさせている。これがすべてだ! 291 | 292 | ビットコインネットワークに直接接続することもできるが、自分の信用できるノードに接続することをおすすめする(そのほうがより早いし、より簡単だ)。 293 | 294 | ## より多くの演習が必要なら: 295 | 296 | Youtube: [How to make your first transaction with NBitcoin](https://www.youtube.com/watch?v=X4ZwRWIF49w) 297 | CodeProject: [Create a Bitcoin transaction by hand.](http://www.codeproject.com/Articles/1151054/Create-a-Bitcoin-transaction-by-hand) 298 | CodeProject: [DotNetWallet - Build your own Bitcoin wallet in C\#](https://www.codeproject.com/script/Articles/ArticleVersion.aspx?waid=214550&aid=1115639) 299 | -------------------------------------------------------------------------------- /bitcoin_transfer/the_blockchain_is_more_than_just_bitcoin.md: -------------------------------------------------------------------------------- 1 | ## “ブロックチェーンは、ビットコインを超えたもの” {#the-blockchain-is-more-than-just-bitcoin} 2 | 3 | 「ブロックチェーンは、ビットコインを超えたもの。」 4 | 5 | おもしろいことに、2つの異なるグループによってこのセンテンスが使われることがある。 6 | 貨幣としてのビットコインを信じている人たちが、ビットコインの価値が上がる強気な予想のための主張として使われる。 7 | また貨幣としてはビットコインが成功するとは信じていない人たちによっては、なぜビットコインがこんなにも興味を引いているかを説明するのに使われる。 8 | 9 | しかし1つ私たち皆が合意できることがある。検閲も改ざんや削除もできない普遍のデータベースが、世界中に分散して存在している、これは他の産業にとてつもないインパクトを与えるだろうということだ。 10 | 11 | 裁判所で使うことができる事実を記録する公証人だったら、ブロックチェーンに永久にそのドキュメントを保存できる。資産や所有権がビットコインブロックチェーンに保存されたり、ブロックチェーン上で移動するようになれば、監査は自動化され、監査内容は立証可能となるだろう。送金人は皆、公に自分の支払い能力を証明することができる。人の仲介や中央管理者の許可なく、自動的に交換するスクリプトでトレードができる。 12 | 13 | この本の続きで、これらの技術のすべてまたはより多くのことを可能とするために必要とする、基本を解説する。すべてはビットコインを使うことから始まる。 14 | -------------------------------------------------------------------------------- /bitcoin_transfer/transaction.md: -------------------------------------------------------------------------------- 1 | ## トランザクション {#transaction} 2 | 3 | > \([Mastering Bitcoin](https://github.com/bitcoinbook/bitcoinbook/)\) トランザクションは、ビットコインシステムの中で最も重要な部分です。システムの他の要素はすべて、トランザクションが作成され、ビットコインネットワークを伝搬し、検証され、最後にグローバルなトランザクション元帳(ブロックチェーン)に追加されるという、一連の流れを支えるように作られています。トランザクションは、ビットコインシステムの参加者間の価値の移転をエンコードしたデータ構造です。個々のトランザクションは、複式簿記の元帳であるブロックチェーンに記された、誰でも見ることができる取引記録です。 4 | 5 | トランザクションには受け取り手がいないかもしれないし、複数いることもあるかもしれない。**それは送り手にも同じことが言える!** ビットコインブロックチェーン上では、前章で示したとおり、送り手と受け取り手は、常にScriptPubKeyによって抽象化されている。 6 | 7 | もしビットコインコアを使っていたら、Transactionsタブをクリックすると、このようにトランザクションを参照できる。 8 | 9 | ![](../assets/BitcoinCoreTransaction.png) 10 | 11 | ここで**Transaction ID**に着目してみたい。上図のケースだと以下がTransaction IDである。 12 | 13 | `f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94` 14 | 15 | > 注釈:Tranaction IDは「SHA256\(SHA256\(txbytes\)\)」と定義できる。 16 | > 17 | > 注釈:承認されていないトランザクションを扱うときにTransaction IDを使ってはいけない。Transaction IDは承認される前は改ざんできてしまうからだ。これを「トランザクション展性」という。 18 | 19 | Blockchain.infoのようなブロックエクスプローラーでトランザクションを閲覧することができる。 [https://blockchain.info/tx/f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94](https://blockchain.info/tx/f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94) 20 | しかし開発者としてはおそらく、より簡単にクエリを実行したりパースしたりすることができるサービスがほしいと思うだろう。 21 | C\#の開発者、そしてNBitcoinのユーザーとしては、Nicolas Dorierの[QBit Ninja](http://docs.qbitninja.apiary.io/#)が最適な選択肢だと思う。ブロックチェーンに対してクエリを発行でき、またウォレットを追跡するためのオープンソースのWebサービスAPIである。 22 | QBit NinjaはMicrosoft Azure Storageを基盤としている[NBitcoin.Indexer](https://github.com/MetacoSA/NBitcoin.Indexer)に依拠している。C\#開発者にはこのAPIのラッパーは開発せず、クライアントライブラリーである[NuGet client package](http://www.nuget.org/packages/QBitninja.Client)を使うことをお勧めする。 23 | 24 | [http://api.qbit.ninja/transactions/f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94](http://api.qbit.ninja/transactions/f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94)にアクセスしてみると、トランザクションの内容を見ることができる。 25 | 26 | ![](../assets/RawTx.png) 27 | 28 | 次のコードを使って16進数表現のトランザクションをパースできる。 29 | 30 | ```cs 31 | Transaction tx = new Transaction("0100000..."); 32 | Console.Writeline(tx); 33 | ``` 34 | 35 | 出力された情報の多さで怖くなる前に、出力タブを閉じてくれ。QBit NinjaクライアントがAPIに対して問い合わせをして情報をパースしてくれる。**QBitNinja.Client** の NuGet packageをインストールしてみよう。 36 | 37 | ![](../assets/QBitNuGet.png) 38 | 39 | Transaction IDを使ってトランザクションのクエリを発行してみよう。 40 | 41 | ```cs 42 | // QBitNinjaクライアントオブジェクトを作成 43 | QBitNinjaClient client = new QBitNinjaClient(Network.Main); 44 | // 文字型のトランザクションIdをパースしてuint256型に変換。これで、クライアントオブジェクトに渡せる。 45 | var transactionId = uint256.Parse("f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94"); 46 | // トランザクションをQBitNinjaサーバー側に問い合わせる 47 | GetTransactionResponse transactionResponse = client.GetTransaction(transactionId).Result; 48 | ``` 49 | 50 | 変数 **transactionResponse** の型は**GetTransactionResponse**で、QBitNinja.Client.Modelsのネームスペースに定義されている。この変数から **NBitcoin.Transaction** 型のオブジェクトを取り出せる。 51 | 52 | ```cs 53 | NBitcoin.Transaction transaction = transactionResponse.Transaction; 54 | ``` 55 | 56 | これら2つのクラスから Transaction IDを取り出す例を見てみよう。 57 | 58 | ```cs 59 | Console.WriteLine(transactionResponse.TransactionId); // f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94 60 | Console.WriteLine(transaction.GetHash()); // f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94 61 | ``` 62 | 63 | **GetTransactionResponse** はトランザクションの中で消費されようとしているインプットの値や、インプットのScriptPubKeyのようなトランザクションデータに含まれない追加的な情報を含んでいる。 64 | 65 | ここで言及したい重要な部分は **インプット** と **アウトプット** である。1つのScriptPubKeyに13.19683492BTCが送られていることがわかるだろう。 66 | 67 | ```cs 68 | List receivedCoins = transactionResponse.ReceivedCoins; 69 | foreach (var coin in receivedCoins) 70 | { 71 | Money amount = (Money) coin.Amount; 72 | 73 | Console.WriteLine(amount.ToDecimal(MoneyUnit.BTC)); 74 | var paymentScript = coin.TxOut.ScriptPubKey; 75 | Console.WriteLine(paymentScript); // これは ScriptPubKey 76 | var address = paymentScript.GetDestinationAddress(Network.Main); 77 | Console.WriteLine(address); 78 | Console.WriteLine(); 79 | } 80 | ``` 81 | 82 | QBitNinjaのGetTransactionResponseクラスを使って、「受け取った」BTCの情報を表示した。 83 | **Exercise :** QBitNinjaのGetTransactionResponseクラスを使って、「使われた」BTCの情報を表示してみよう! 84 | 85 | さて今度は、NBitcoinのTransactionクラスを使って、QBitNinjaで表示した「受け取った」BTCの情報と同じものを、どのように表示するか見てみよう。 86 | 87 | ```cs 88 | var outputs = transaction.Outputs; 89 | foreach (TxOut output in outputs) 90 | { 91 | Money amount = output.Value; 92 | 93 | Console.WriteLine(amount.ToDecimal(MoneyUnit.BTC)); 94 | var paymentScript = output.ScriptPubKey; 95 | Console.WriteLine(paymentScript); // これは ScriptPubKey 96 | var address = paymentScript.GetDestinationAddress(Network.Main); 97 | Console.WriteLine(address); 98 | Console.WriteLine(); 99 | } 100 | ``` 101 | 102 | では、インプットとなっているトランザクションを見てみよう。見てみると、1つ前のトランザクションのアウトプットが参照されているのに気づくだろう。各インプットトランザクションが、いま着目しているトランザクションにBTCを充てるためにどのアウトプットを使っているかを示している。 103 | 104 | ```cs 105 | var inputs = transaction.Inputs; 106 | foreach (TxIn input in inputs) 107 | { 108 | OutPoint previousOutpoint = input.PrevOut; 109 | Console.WriteLine(previousOutpoint.Hash); // 1つ前のトランザクションのハッシュ値=トランザクションID 110 | Console.WriteLine(previousOutpoint.N); // 1つ前のトランザクションのアウトプットのインデックス値。これは、今回のトランザクションで消費される。 111 | Console.WriteLine(); 112 | } 113 | ``` 114 | 115 | **TxOut**、**Output**と**out**は同義語である。 116 | **OutPoint** と混同してはいけないが、この点については後ほど触れる。 117 | 118 | 要約すると、あるTxOutとはビットコインの額とその受け取り手の**ScriptPubKey**の組み合わせを示す。 119 | 120 | ![](../assets/TxOut.png) 121 | 上図のとおり、いま対象のトランザクションにある一番最初のScriptPubKeyから21BTCを支払うトランザクションアウトプットを作ってみよう。 122 | 123 | ```cs 124 | Money twentyOneBtc = new Money(21, MoneyUnit.BTC); 125 | var scriptPubKey = transaction.Outputs.First().ScriptPubKey; 126 | TxOut txOut = new TxOut(twentyOneBtc, scriptPubKey); 127 | ``` 128 | 129 | すべての**トランザクションアウトプット**は、それを包含するトランザクションのIDと、そしてトランザクションの中で何番目のアウトプットかを示すインデックスにより、ブロックチェーン全体の中で一意に識別される。その一意に識別できる情報のことを**OutPoint**と呼ぶ。 130 | 131 | ![](../assets/OutPoint.png) 132 | 133 | 例えば、いま対象にしているトランザクションの13.19683492 BTCのアウトプットのOutpointは以下である。\(f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94, 0\). 134 | 135 | ```cs 136 | OutPoint firstOutPoint = receivedCoins.First().Outpoint; 137 | Console.WriteLine(firstOutPoint.Hash); // f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94 138 | Console.WriteLine(firstOutPoint.N); // 0 139 | ``` 140 | 141 | さて、インプット(すなわちトランザクションインプット)に目を向けてみよう。 142 | 143 | ![](../assets/TxIn.png) 144 | 145 | **トランザクションインプット**は支払いに使おうとしているトランザクションアウトプットの**Outpoint**と**ScriptSig**(ScriptSigは所有権の証明とも言える)によって構成されている。今題材にしているトランザクションでは現に9つのインプットがある。 146 | 147 | ```cs 148 | Console.WriteLine(transaction.Inputs.Count); // 9 149 | ``` 150 | 151 | 過去のoutpointのトランザクションIDを使って、そのトランザクションに関連付けられた情報を参照できる。 152 | 153 | ```cs 154 | OutPoint firstPreviousOutPoint = transaction.Inputs.First().PrevOut; 155 | var firstPreviousTransaction = client.GetTransaction(firstPreviousOutPoint.Hash).Result.Transaction; 156 | Console.WriteLine(firstPreviousTransaction.IsCoinBase); // コインベーストランザクションではない。 157 | ``` 158 | 159 | > 日本語版注:firstPreviousOutPointは、NBitcoinで1つめのインプットの元となった過去のトランザクションのアウトポイントを参照している。2行目ではアウトポイントから得られたトランザクションハッシュ/トランザクションIDを、QBit Ninjaクライアントに渡してトランザクションの情報を取得している。 160 | 161 | やろうと思えばこの方法を使って、**コインベーストランザクション**、つまりマイナーによって新しく発掘されたコインのトランザクション(すなわち、それ以前のトランザクションは存在しない)にたどり着くまで、トランザクションIDをさかのぼり続けることができる。 162 | **Exercise**:題材にしているトランザクションの1番目のインプットを過去にさかのぼり、コインベーストランザクションを見つけよう! 163 | ヒント:私は数分後、30~40トランザクションさかのぼったときに諦めた。 164 | 165 | そう、君の推測は正しい。これを行うのは効率的な方法ではないが、良い練習になる。 166 | 167 | 今の題材の例では、過去のアウトプットの合計は13.19**70**3492 BTCであった。 168 | 169 | ```cs 170 | Money spentAmount = Money.Zero; 171 | foreach (var spentCoin in spentCoins) 172 | { 173 | spentAmount = (Money)spentCoin.Amount.Add(spentAmount); 174 | } 175 | Console.WriteLine(spentAmount.ToDecimal(MoneyUnit.BTC)); // 13.19703492 176 | ``` 177 | 178 | このトランザクションでは、13.19**68**3492 BTCが受け取られている。 179 | 180 | **Exercise:** 使用したコインを取得したのと同じように、受け取ったコインの総量を取得してみよう。 181 | 182 | 0.0002 BTC(言い換えれば13.19**70**3492 - 13.19**68**3492)が計上されていないということだ!インプットとアウトプットの差は**トランザクション手数料**あるいは**マイニング手数料**と言われている。これはマイナーに、与えられたトランザクションをブロックに含めてもらうために渡す手数料である。 183 | 184 | ```cs 185 | var fee = transaction.GetFee(spentCoins.ToArray()); 186 | Console.WriteLine(fee); 187 | ``` 188 | 189 | 注意してほしいのだが、**コインベーストランザクション** だけは、そのアウトプットの値がインプットの値より高い。これは事実上コインの創造に相当する。よって定義上、コインベーストランザクションに手数料は存在しない。コインベーストランザクションはすべてのブロックの最初のトランザクションとなっている。 190 | コンセンサスルールによって、コインベーストランザクションの中のアウトプットの値の合計は、ブロック内のトランザクション手数料の合計とマイニング報酬の和を超えないようになっている。 191 | 192 | -------------------------------------------------------------------------------- /cover.md: -------------------------------------------------------------------------------- 1 | 2 | ![](assets/bitcoin.png) 3 | 4 | # Programming The Blockchain in C**\#** 5 | _Authored by Nicolas Dorier 6 | Creator of NBitcoin, The .NET Bitcoin Framework_ 7 | 8 | _Co-authored with Bill Strait 9 | Founder of Billd Labs_ 10 | 11 | _And nopara73 12 | Just a geek_ 13 | -------------------------------------------------------------------------------- /foreword.md: -------------------------------------------------------------------------------- 1 | # 前書き {#foreword} 2 | 3 | これは私の心に響いたアイン・ランド作の『水源』からの引用である。 4 | 5 | > ゲイル・ワイナンド、世界を操るもの、とハワード・ローク、主人公である建築家が、一緒に議論している。ゲイルは、なぜか分からないが、ロークといるときに不思議な解放感を感じることに気づく。 6 | > ワイナンドが尋ねる: 7 | > "ハワード、君は恋に落ちたことはあるかい?" 8 | > ロークは、彼のほうへ向き、まっすぐみて静かに答えた: 9 | > "いまも恋に落ちているよ。" 10 | > "でも、建物の中を歩いている時、その気持ちは、建物よりも大きいかい?" 11 | > "かなりね、ゲイル。" 12 | > "地球では幸せにはなれないなんていう人たちのことを、考えていた。彼らがどれだけ懸命に、人生の中に喜びを見つけようとしているか見てみろよ。そして、どれだけ、そのためにもがいているか。どうして生きとし生けるものが、苦しみの中に存在する必要がある? 一体どんな権利があって、人間が自分自身の喜びなしに存在しなければならないんだよ。みんなそれを欲しがってる。体全体で欲しがっているというのに。でも、見つけられないんだ。なぜか分からないよ。彼らは、愚痴をいって、人生の意味が分からないというんだ。俺が軽蔑するタイプのやつらはな、ある種の高い目的もしくは、いわゆる”普遍的な目標”を追い求めているやつらだ。やつらは、何のために生きてるかをしらず、”自分自身を見つける”必要があると、嘆くんだ。君も周りでそんなのを聞くだろ。それがどうも、今世紀における公式に常識のようだよ。開く本、開く本。口々に言われるたわいもない自己開示。 いかにも、高尚な告白のように言われてる。私は、そんなのは、最も恥ずべきことだと考えるよ。" 13 | > "ゲイル"。ロークは、立ち上がり、手を伸ばし、太い枝を木から折って、両端を、閉じて両手で持った。そして、手首と指の付け根で木の抵抗に反して、枝をゆっくり弧の形に曲げた。"これで、私は、自分の好きなものをこいつから作ることができる。弓、槍、杖、さく。これが人生の意味さ。" 14 | > "君の強さってことかい?" 15 | > "仕事さ。" 彼は、枝を横にほおり投げた。"地球は材料を提供する、そして、それをもとに、我々は、なにかを作るのだ。" 16 | 17 | 私が思うに、ビットコインブロックチェーンはこの小説に出てくる木の枝なのではないか。ブロックチェーンは興味のない人にとってみれば、うんざりするし役に立たないビットの集まりのように思えるだろう。しかしプログラマーや起業家にとってみたら、私たちの想像によってどんなかたちにも変えられる素晴らしい原石なのだ。私たちこそがビットコインブロックチェーンに意味と目的を吹き込むのである。 18 | 19 | 枝から弓、槍や杖を作ることのできる木を知る必要があるように、ビットコインブロックチェーンを形作ることのできるプログラミングを知る必要がある。興味のない人が思う役に立たないビットの集まりを、スキルと賢さでどんなものにでも形作ることができるということに気づいてもらえることを願う。 20 | 21 | ここで警告させてほしい。ビットコインを学ぶことは映画『マトリックス』で出てきた赤い錠剤を手にするようなものだ。いつのまにか自分が、今の仕事をやめて、ビットコインにフルタイムで没頭する気になっているかもしれない。 22 | 23 | この本によってビットコインブロックチェーンの利用方法を基礎から応用まで学べる。API(ビットコインコアから提供されているRPCのAPIなど)の利用方法が学べるのではなく、APIそのものの作り方が学べるだろう。 24 | 25 | > ナカモトサトシはかつて、ビットコインを「色で言うと退屈なグレー」と表現した。 26 | 27 | APIにあわせてプログラミングすればアプリケーションを早くローンチできるが、そのAPIによってイノベーションを起こせなくなってしまうこともある。ビットコインブロックチェーンを完全に理解すれば、開発者はそのポテンシャルを完全に開放できる。 28 | -------------------------------------------------------------------------------- /implementations/README.md: -------------------------------------------------------------------------------- 1 | # ケース・スタディ {#implementations} 2 | 3 | In this chapter you will see how existing implementations are made on top of NBitcoin. 4 | You will be guided through the code and the design decisions the developer had to make. 5 | This section is more practical. What you learn here will come handy when you face similar challenges the developers of specific implementations has already faced. 6 | -------------------------------------------------------------------------------- /implementations/hiddenbitcoinkey_storage_hd_wallet_md.md: -------------------------------------------------------------------------------- 1 | # HiddenWallet:鍵の管理\(HD ウォレット\) {#hiddenbitcoin-keystorage} 2 | 3 | \([nopara73](https://github.com/nopara73)\)私は[HiddenWallet](https://github.com/nopara73/HiddenWallet)というプライバシー重視のビットコインウォレットを開発している。[HiddenBitcoin](https://github.com/nopara73/HiddenWallet)のライブラリーはNBitcoinとユーザーインターフェースの間の抽象化レイヤーの導入となっている。 4 | 5 | ビットコインウォレットには3つの重要な機能があり、このケーススタディーはその3つで構成するつもりだ。 6 | 7 | 1. 安全に鍵を保管し、鍵へのアクセスを管理する 8 | 2. ビットコインブロックチェーン上のこれらの鍵や他の鍵を監視する 9 | 3. トランザクションを生成し、それらをブロードキャストする 10 | 11 | このレッスンでは鍵のストレージ機能に取り組むつもりだ。 12 | もしより広い範囲でコードを確かめてみたければ、[GitHub](https://github.com/nopara73/HiddenBitcoin)にソリューションがあるので見てほしい。 13 | ただ早くウォレットをセットアップして使う方法を知りたければ、[CodeProject](https://www.codeproject.com/articles/1096320/hiddenbitcoin-high-level-csharp-bitcoin-wallet-lib)によりハイレベルなチュートリアルがある。 14 | 15 | **どのくらいハイレベルか?**私見では、GUIディベロッパーやデザイナーでもそんなに多くのミスは起こさないはずだ。彼らはインプット、アウトプットやscriptPubKeyについて知らないかもしれない。ただ彼らはビットコインアドレス、秘密鍵とウォレットのレベルはしっかり理解しているはずだ。NBitcoinも十分に抽象化されるようにしている。 16 | 17 | ## 鍵を保管するデザインの決定 18 | 19 | 秘密鍵を保管するときになにを決めなければならないかと、それらを作るときになにを気に留めるべきかについての、テンプレートを提示するのにとても良いタイミングだ。 20 | 21 | ### 1つの鍵しか使わないケース 22 | 23 | これが手っ取り早い。ただ、僕がこの道を行くのが正しいと思うシチュエーションはそんなに多くはない。しかし、あなたのニーズに最も適していることもありえなくはないだろう。 24 | 悪い例としてここに私が作った、1つしか鍵を使わないビットコインウォレットのイラストレーションを示そう。結論を考えるために残しておこう。 25 | 26 | ![](../assets/TransparentWallet2.png) 27 | 28 | ### JBOKウォレット 29 | 30 | JBOKウォレットはひと束の鍵(**J**ust a **B**unch **O**f **K**eys)をまとめるものだ。リファレンスを書いている時点で、鍵を保管するためにクライアントでこのメソッドを使っている。 31 | これの問題はユーザーが定期的にバックアップをとらなければならないということだ。しかしもし鍵をインポートしたり、鍵を紙にメモしたり、パスワードを変えたりすることをできるようにしたいなら、この機能を使うか、この機能と決定性ウォレットをあわせて使うようなことをする必要がある。私はこれを使わないと決めた。というのは私のHiddenWalletをプライバシー向上のために改良しようとしていたということと、これではなくてより良いウォレット構造を持ち得るからだ。 32 | 33 | ### BIP38 \(Part 2\) - 信頼できないサードパーティーの鍵生成 34 | 35 | 何度も言うことになるが、これは鍵の生成機構のためにパスフレーズを生成するという思想だ。パスフレーズを使えば、パスワードや知らなかったりまったく秘密鍵を知らなかったりしても、暗号化された鍵を生成することができる。 36 | HiddenWalletはデスクトップウォレットだ(そしておそらく、しばらく変えるつもりはない)。ということで鍵の生成や鍵を保管する目的で信頼できないサードパーティーを使う必要がない。だからまだこの機能は実装しないことに決めた。 37 | 38 | ### SHDウォレット 39 | 40 | これは私が組み込んだウォレット構造だ。そう、降参だ。SHDウォレットとは私がたった今思いついた言葉だ。この言葉は標準的な言葉としては存在していないし誰も使っていない。では私の中でこれは何を表しているかというと、不可視な階層的決定性ウォレット(**S**tealth and **H**ierarchical **D**eterministic wallet)だ。これが私が作成したものを表現するのに最適な言葉だ。 41 | コードに入っていく前に不可視にする機能だけ実装したことを注釈しておきたい。なぜならばそれが低いところに成っているフルーツだからだ。ステルスアドレスがビットコイン業界において将来的にどんな使用法にしても使われるかどうかは私は確信を持てていない。 42 | 43 | ステルスアドレスとはこのようなものだ。 `waPXAvDCDGv8sXYRY6XDEymDGscYeepXBV5tgSDF1JHn61rzNk4EXTuBfx22J2W9rPAszXFmPXwD2m52psYhXQe5Yu1cG26A7hkPxs` 44 | 45 | ## ブラックボックス 46 | 47 | **Safe**というクラスを実装した。ブラックボックスとしてこのクラスは直感的に使える。 48 | 49 | ```cs 50 | var network = Network.MainNet; 51 | ``` 52 | 53 | この**Network**は**NBitcoin.Network**ではない。というのはGUIディベロッパーはNBitcoinを使っているとは知らないはずだからだ。また、NBitcoinではより多くのネットワークの選択肢があるが、HiddenBitcoinではそれらを扱うことはできない。現時点でHiddenBitcoinは`MainNet`と`TestNet`をサポートしている。 54 | ネットワークはenumとなっていて、**HiddenBitcoin.DataClasses**のネームスペースで見つけることができる。 55 | 56 | ```cs 57 | string mnemonic; 58 | Safe safe = Safe.Create(out mnemonic, "password", walletFilePath: @"Wallets\hiddenWallet.hid", network); 59 | Console.WriteLine(mnemonic); 60 | ``` 61 | 62 | また、safeクラスをロードしたり復元したりすることができる。 63 | 64 | ```cs 65 | Safe loadedSafe = Safe.Load("password", walletFilePath: @"Wallets\hiddenWallet.hid"); 66 | if (network != loadedSafe.Network) 67 | throw new Exception("WrongNetwork"); 68 | 69 | Safe recoveredSafe = Safe.Recover(mnemonic, "password", walletFilePath: @"Wallets\sameHiddenWallet.hid", network); 70 | ``` 71 | 72 | safeクラスから文字列で鍵を取得することもできる。 73 | 74 | ```cs 75 | Console.WriteLine("Seed private key: " + safe.Seed); 76 | Console.WriteLine("Seed public key: " + safe.SeedPublicKey); 77 | Console.WriteLine("Third child address: " + safe.GetAddress(2)); 78 | Console.WriteLine("First child private key: " + safe.GetPrivateKey(0)); 79 | Console.WriteLine("Second child private key and the corresponding address: "); 80 | Console.WriteLine(safe.GetPrivateKeyAddressPair(1).PrivateKey); 81 | Console.WriteLine(safe.GetPrivateKeyAddressPair(1).Address); 82 | Console.WriteLine("The stealth address: " + safe.StealthAddress); 83 | Console.WriteLine("Scan and spend private keys for stealth payments:"); 84 | Console.WriteLine(loadedSafe.ScanPrivateKey); 85 | Console.WriteLine(loadedSafe.SpendPrivateKey); 86 | ``` 87 | 88 | ``` 89 | Seed private key: xprv9s21ZrQH143K4RBm26TMm3qwTtR3Eyh22xDEN3TBebgfAvHPPSjxxFnFGDtnNHvqZ7pihGmAc8o9y1UvfEzcxSzyXAnmvTBowCNi69nXsqJ 90 | Seed public key: xpub661MyMwAqRbcGuGE87zN8Bng1vFXeSQsQB8qARroCwDe3icXvz4DW46j7U6fX8NsKhqcxR7K1mDX4gTbtvCGdeJz5M7py3yEqMsjUH2DYhb 91 | Third child address: 17pGpPX1A2sCdqJXsC5BiwdFphFVgJR9nk 92 | First child private key: xprv9ubnoo3dgCYfrWbYBEM71WoBvzwTtQemEdjW836CeWJYunYBskQhq3nrJMvNBCCFpnU5GbgbL1b2QbPHA4rRPESEhqfKzae5oWe7SAMuxAV 93 | Second child private key and the corresponding address: 94 | xprv9ubnoo3dgCYfuE1hVB3F3Sh5YFJUNUjyZ68PDzPNhpmtqWDtD45zucZYMUAjY22HNxaY6tsvGAdJdcyALCMm2mTAvA4pEp1m7y3BSccKY4r 95 | 19FHdsj2YT79TuxbWcDMz9opTU28L1memr 96 | The stealth address: vJmuFuLggpgzivm3UUjQguLhMA6C1SnYFJu5N6QkmXYRCU3nG1Ww36VcXy6zXpJvGeVTidxcsu7U19sfB1rxHhzvSNV5eGGLk6G1Cb 97 | Scan and spend private keys for stealth payments: 98 | L5CTS4U27umRfSBu2ztxsyUeMEYzJJk3HvCp3deSQBJWmRSUqCLg 99 | KyXveppF4Xm3KwJgG7EBSi6SxfMTkaDXYYmv7c7xWRcF7yUNpswp 100 | ``` 101 | 102 | **注釈**:理想的にはシードは決して使わないこと。safeクラスの鍵を生成するメソッド(後述)を使って鍵生成を繰り返すことを始めるほうがよりよいプラクティスだ。 103 | 104 | ## ホワイトボックス 105 | 106 | ### Safe.Create 107 | 108 | ```cs 109 | // Creates a mnemonic, a seed, encrypts it and stores in the specified path. 110 | public static Safe Create(out string mnemonic, string password, string walletFilePath, Network network) 111 | { 112 | var safe = new Safe(password, walletFilePath, network); 113 | mnemonic = safe.SetSeed(password).ToString(); 114 | safe.Save(password, walletFilePath, network); 115 | 116 | return safe; 117 | } 118 | ``` 119 | 120 | `safe.SetSeed`によってmnemonic codeを作り、`_seedPrivateKey`をセットできる。最後にmnemonic codeをリターンし、クラスを使っているユーザーに示すことができる。 121 | 122 | ![](../assets/RootKey.png) 123 | 124 | ```cs 125 | private ExtKey _seedPrivateKey; 126 | private Mnemonic SetSeed(string password) 127 | { 128 | var mnemonic = new Mnemonic(Wordlist.English, WordCount.Twelve); 129 | 130 | _seedPrivateKey = mnemonic.DeriveExtKey(password); 131 | 132 | return mnemonic; 133 | } 134 | ``` 135 | 136 | ### safe.Save 137 | 138 | ウォレットのファイルを保存する。問題はその中に何を保存するかだ。 139 | 140 | ```json 141 | { 142 | "EncryptedSeed":"6PYXR8U5Nu9UoGZcU95DWWKCXppKnYBUKyJgze6DX6bQDNwFzNdJApUzXT", 143 | "ChainCode":"C+2MiZU7R/33bkvgdDqdQp7xx3nXHSIzS6bUgRsnaus=", 144 | "Network":"MainNet" 145 | } 146 | ``` 147 | 148 | ウォレットファイルはJSONフォーマットだ。 149 | 拡張鍵からチェーンコードと秘密鍵を取得することができるし、逆もできる。 150 | 151 | ```cs 152 | Key privateKey = _seedPrivateKey.PrivateKey; 153 | byte[] chainCode = _seedPrivateKey.ChainCode; 154 | ``` 155 | 156 | 最後に秘密鍵を暗号化する。 157 | 158 | ![](../assets/EncryptedKey.png) 159 | 160 | ```cs 161 | string encryptedBitcoinPrivateKeyString = privateKey.GetEncryptedBitcoinSecret(password, _network).ToWif(); 162 | string chainCodeString = Convert.ToBase64String(chainCode); 163 | string networkString = network.ToString(); 164 | ``` 165 | 166 | ### Safe.Load 167 | 168 | 保存するプロセスを逆方向にたどってみよう。 169 | 170 | ```cs 171 | public static Safe Load(string password, string walletFilePath) 172 | { 173 | if (!File.Exists(walletFilePath)) 174 | throw new Exception("WalletFileDoesNotExists"); 175 | 176 | var walletFileRawContent = WalletFileSerializer.Deserialize(walletFilePath); 177 | 178 | var encryptedBitcoinPrivateKeyString = walletFileRawContent.EncryptedSeed; 179 | var chainCodeString = walletFileRawContent.ChainCode; 180 | 181 | var chainCode = Convert.FromBase64String(chainCodeString); 182 | 183 | Network network; 184 | var networkString = walletFileRawContent.Network; 185 | if (networkString == Network.MainNet.ToString()) 186 | network = Network.MainNet; 187 | else if (networkString == Network.TestNet.ToString()) 188 | network = Network.TestNet; 189 | else throw new Exception("NotRecognizedNetworkInWalletFile"); 190 | 191 | var safe = new Safe(password, walletFilePath, network); 192 | 193 | var privateKey = Key.Parse(encryptedBitcoinPrivateKeyString, password, safe._network); 194 | var seedExtKey = new ExtKey(privateKey, chainCode); 195 | safe._seedPrivateKey = seedExtKey; 196 | 197 | return safe; 198 | } 199 | ``` 200 | 201 | ここにSafeクラスのコンストラクタの中で何をしているかを示す。 202 | 203 | ```cs 204 | private Safe(string password, string walletFilePath, Network network) 205 | { 206 | SetNetwork(network); 207 | 208 | SetSeed(password, mnemonicString); 209 | 210 | WalletFilePath = walletFilePath; 211 | } 212 | ``` 213 | 214 | ### SetNetwork 215 | 216 | このクラスの中では`NBitcoin.Network`を使いたい。だからそれをprivateのメンバーとしてセットしよう。 217 | 218 | ```cs 219 | private NBitcoin.Network _network; 220 | private void SetNetwork(Network network) 221 | { 222 | if (network == Network.MainNet) 223 | _network = NBitcoin.Network.Main; 224 | else if (network == Network.TestNet) 225 | _network = NBitcoin.Network.TestNet; 226 | else throw new Exception("WrongNetwork"); 227 | } 228 | ``` 229 | 230 | ### Safe.Recover 231 | 232 | ```cs 233 | public static Safe Recover(string mnemonic, string password, string walletFilePath, Network network) 234 | { 235 | var safe = new Safe(password, walletFilePath, network, mnemonic); 236 | safe.Save(password, walletFilePath, network); 237 | return safe; 238 | } 239 | ``` 240 | 241 | これを動かすために、コンストラクタを拡張しなければならない。 242 | 243 | ```cs 244 | private Safe(string password, string walletFilePath, Network network, string mnemonicString = null) 245 | { 246 | SetNetwork(network); 247 | 248 | if (mnemonicString != null) 249 | { 250 | var mnemonic = new Mnemonic(mnemonicString); 251 | _seedPrivateKey = mnemonic.DeriveExtKey(password); 252 | } 253 | 254 | WalletFilePath = walletFilePath; 255 | } 256 | ``` 257 | 258 | ### Getters 259 | 260 | ここにはどのようにして鍵を引き出すかを示してある。私の目的としては複雑なキーパスを使うことはあまり意味をなさない。 261 | 262 | ```cs 263 | public PrivateKeyAddressPair GetPrivateKeyAddressPair(int index) 264 | { 265 | var foo = _seedPrivateKey.Derive(index, true).GetWif(_network); 266 | return new PrivateKeyAddressPair 267 | { 268 | PrivateKey = foo.ToWif(), 269 | Address = foo.ScriptPubKey.GetDestinationAddress(_network).ToWif() 270 | }; 271 | } 272 | ``` 273 | 274 | ### Stealth 275 | 276 | ```cs 277 | private Key _spendPrivateKey => _seedPrivateKey.PrivateKey; 278 | public string SpendPrivateKey => _spendPrivateKey.GetWif(_network).ToWif(); 279 | private Key _scanPrivateKey => _seedPrivateKey.Derive(0, hardened: true).PrivateKey; 280 | public string ScanPrivateKey => _scanPrivateKey.GetWif(_network).ToWif(); 281 | 282 | public string StealthAddress => new BitcoinStealthAddress 283 | (_scanPrivateKey.PubKey, new[] {_spendPrivateKey.PubKey}, 1, null, _network 284 | ).ToWif(); 285 | ``` 286 | 287 | 288 | 289 | -------------------------------------------------------------------------------- /introduction/README.md: -------------------------------------------------------------------------------- 1 | # イントロダクション {#introduction} 2 | -------------------------------------------------------------------------------- /introduction/complementary_reading.md: -------------------------------------------------------------------------------- 1 | ## 参考文献 {#complementary-reading} 2 | 3 | この本の内容を完全に理解するために使える文献を以下に紹介する。 4 | 5 | * [Mastering Bitcoin of Andreas M. Antonopoulos](https://github.com/bitcoinbook/bitcoinbook) 6 | * [The Bitcoin Developer’s Reference Guide](https://bitcoin.org/en/developer-guide) 7 | * [Nicolas Dorier’s articles on CodeProject](http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=6354608) 8 | * [nopara73's articles on CodeProject](http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=10170217) 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /introduction/crowdfunding_this_book.md: -------------------------------------------------------------------------------- 1 | ## この本へのクラウドファンディング {#crowdfunding-this-book} 2 | 3 | 私たちが読者のための素晴らしい本を作り続けたいなら、ピザ、寿司やコーヒーを買う必要がある。そのために十分なビットコインをいただくことに見合う責任が、私たちにはあるということでもある。また、私たちはとても怠け者なので、この本を書き続けるためにもぜひ読者のフィードバックをいただきたい。 4 | 5 | **Bitcoin address:** [1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB](https://blockchain.info/address/1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB) 6 | 7 | 仮想通貨中毒者がひょっとすると言うかもしれない。「Proof of StakeやProof of Workが最も良い愛情表現だ。それ以外すべてが法定通貨なのだ。」 8 | 9 | より詳細に私たちの仕事を知りたいと思っていただいたなら、[こちら](http://n.bitcoin.ninja/)を参照いただきたい。 10 | -------------------------------------------------------------------------------- /introduction/diagrams.md: -------------------------------------------------------------------------------- 1 | ## 図解について {#diagrams} 2 | 3 | この本で使用するほとんどの図解では、同じ図を使用する。矢印については、2つの矢印に囲まれているオブジェクトは、その2つの要素から作られるという意味で使っている。 4 | 5 | たとえば以下の図解で言えば、このように読む。 6 | 7 | ```Key + Password = EncryptedKey``` 8 | ```EncryptedKey + Password = Key``` 9 | 10 | ![](../assets/encrypted_key.png) 11 | 12 | コードも理解するために良い方法なのだが、時としてたくさんの言葉を使うよりも図のほうが簡単に表せる。(心配しないでいただきたいのだが、もちろんコードも紹介する。) 13 | -------------------------------------------------------------------------------- /introduction/license_cc_asa_3u.md: -------------------------------------------------------------------------------- 1 | ## ライセンス:クリエイティブ・コモンズ \(ASA 3U\) {#license-cc-asa-3u} 2 | 3 | あなたは クリエイティブ・コモンズ・ライセンスの「表示-継承 3.0 非移植」([CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/deed.ja))に従う限り、このドキュメントを自由に配布しても変更しても構いません。 4 | 5 | ![](../assets/ccasa3u.png) 6 | -------------------------------------------------------------------------------- /introduction/pre-requisites.md: -------------------------------------------------------------------------------- 1 | ## 前提事項 {#pre-requisites} 2 | 3 | ### スキル {#skills} 4 | 5 | * 関数型プログラミングとオブジェクト指向プログラミングに抵抗がない。 6 | * C\#の基礎を理解していると良いが、C\#はJavaや他のC型言語習得者にも読みやすいと思われる。 7 | * 数学の知識は必要ない。安全なサービスを作るために知る必要のある最低限以上の暗号学の知識はカバーしない。 8 | * ビットコインに対する深い知識は必要ない。 9 | 10 | ### ツール {#tools} 11 | 12 | * [Visual Studio Community Edition](https://www.visualstudio.com/)(Windows) もしくは、 13 | [Xamarin Studio](https://store.xamarin.com) (Mac and Linux)。両方とも無料。 14 | * [Bitcoin Core](https://bitcoin.org/en/bitcoin-core/) 持っていれば理想だが、持ってなくても読み進められる。 15 | 16 | > **ヒント:** もしハードディスクの容量が足りなくてフルノードに躊躇してるのであれば、pruningモードでBitcoin Coreを動かすことを考えてほしい。古い履歴を廃棄すること以外は、フルノード(ビットコインコアをインストールしていて、すべての取引履歴=ブロックを持っているノード)と同じ動きをする。 17 | -------------------------------------------------------------------------------- /introduction/project_setup.md: -------------------------------------------------------------------------------- 1 | ## プロジェクトのセットアップ {#project-setup} 2 | 3 | 説明を始める前に、どのようにVisual StudioまたはXamarin等でプロジェクトをセットアップするかを示す。 4 | 5 | 1. 新規プロジェクトを作成する(.NET 4.5以上) 6 | 2. ソリューションエクスプローラーの「参照」で右クリックし、「NuGet パッケージの管理」をクリック 7 | 3. 「**NBitcoin**」を検索しインストールする。 8 | ![](../assets/nuget_jp.png) 9 | 10 | > **ヒント:** MacやLinuxでも、NBitcoin.Monoではなく、NBitcoinを使うこと。 11 | 12 | NBitcoinは、この本のメイン筆者であるNicolas Dorierがメンテナンスしている、.NETで作られたオープンソースライブラリである。C\#でビットコインのソフトウェアを開発するのであれば、このライブラリを使うべきだろう。NBitcoinはクロスプラットフォームアプリケーションをサポートする。 13 | 14 | ### NBitcoinのソースコードをデバッグする方法(オプション) 15 | 16 | いろいろと簡単に調べられるように、NBitcoinは、そのソースコード内をデバッグできるようにしてある。この機能が使えるようにするためには、Visual Studioのツール/オプション/デバッグで「ソースサーバーサポートを有効にする」をチェックする必要がある。 17 | ![](../assets/visualstudio_enablesourceserversupport_jp.png) 18 | 19 | これで、もしNBitcoinのコードにステップインをすると、ソースコードがGitHubから自動的に取得され、visual studioのデバッガーに表示される。 20 | 21 | -------------------------------------------------------------------------------- /introduction/why_blockchain_programming_and_not_bitcoin_program.md: -------------------------------------------------------------------------------- 1 | ## なぜ ビットコインプログラミングではなく、ブロックチェーンプログラミング ? {#why-blockchain-programming-and-not-bitcoin-programming} 2 | 3 | ビットコインにとってのブロックチェーンとは、宝石にとっての金の関係と似ている。 4 | 5 | 私たちはビットコインを、金貨ではなくむしろ宝石に例えた。それは金の最初のキラーアプリが宝石だからだ。貨幣はその後だった。 6 | 7 | ブロックチェーンに価値あるとはいえ、ビットコインには価値ない、と勘違いしないでほしい。もし金に価値があるなら、金のネックレスを誰が投げ捨てるだろうか。ブロックチェーンはビットコインがあるから成り立ち、そのおかげで繁栄している。ブロックチェーンの価値が上がることによって、ビットコインを使うために支払われる量は増えるし、需要が増えるだろう。 8 | 9 | あなたが作るアプリケーションの中で「通貨としてのビットコイン」という機能を使うかどうかは、あなた自身に委ねられているのだ。 10 | 11 | ブロックチェーンは原石で、ビットコインは燃料だ。通貨としてのビットコインは、誰かがこの燃料は交換の良い媒体でもあると考えたときにいつも出てくる特徴の1つだ。ビットコインブロックチェーンを使って、価値を交換することよりももっと多くのことを実装できる。通貨としての価値を信じる必要さえない。私たちはこの本でビットコインを通貨としてどのように使うかを伝えるが、それだけではないのだ! 12 | 13 | -------------------------------------------------------------------------------- /introduction/why_c.md: -------------------------------------------------------------------------------- 1 | ## なぜ C\# か? {#why-c} 2 | 3 | .NET Framrworkは企業の利用環境で人気がある。同時に.NETはスタートアップや趣味プログラマーのためにも完璧なツールであると信じている。 4 | 5 | * iOS、Android、WindowsタブレットやWindowsフォン、デスクトップ、サーバーや埋め込みデバイス等のうえで動作するコードを無料で作ることができる。 6 | * コンパイラーからコアランタイムまですべてがオープンソースである。 7 | * BizSparkプログラムによって、あらゆるスタートアップはMicrosoftのすべてのツールを、月150ドル分のAzureサービス含めて、無料で利用できる。 8 | * Visual Studio Community 2015は、趣味プログラマーにとっても無料で使うことのできるプロ用のIDEである。 9 | * C\#はJavaやC++ととても関連性が強い。そのため、たくさんの開発者にとって読むのが簡単だ。 10 | * この本の執筆者の1人であるNicolas Dorierが、NBitcoinと呼ばれる、.NETで動作する最も人気のあるビットコインのフレームワークを作った。 11 | * 私が会ったことのあるC\#を学んだ人は皆、C\#が1番良い言語だと言うだろう。たとえその人が今C\#を使っていないとしても。 12 | 13 | この本の執筆者達は15年以上、C\#の経験を積んできた。楽しさを追求するプロジェクトであれ、利益を求めるプロジェクトであれ、C\#は私たちが頼りにできる言語だ。 14 | 15 | > 私たちはMicrosoftからお金をもらって広告をしているのではない。C\#好きになるのであればまだ遅くはない。 16 | -------------------------------------------------------------------------------- /introduction/why_do_people_hate_bitcoin.md: -------------------------------------------------------------------------------- 1 | ## なぜこの本を読むべきか? {#why-do-people-hate-new-technologies-bitcoin} 2 | 3 | ビットコインを理解することは大きなチャレンジとなる。ひょっとするとビットコインにまったく馴染みがないかもしれない。もしかして数年間ビットコインの情報をフォローしていてとても時間を費やしていて、すでに完全に中毒状態なのにも関わらず、いまだ全体的には大きな取っ散らかった状態のように思えているかもしれない。もしくはビットコインを理解していると思っているかもしれないが、実践的な知識がいまだ欠けているかもしれない。もしあなたがこれらのどれかにあたるなら、この本があなたの時間を費やすべき最も良い投資になると確信している。 4 | 5 | 私たちにビットコインブロックチェーンの世界を案内させてもらえるなら、どんな[redditのビットコイン](https://www.reddit.com/r/Bitcoin/)の議論でも勝つために必要なスキルで読者を武装するだけではなく、今後日々現れる数え切れない開発の機会の中から、良いものを賢く選択できる力が身につくだろう。さらにそれらのアイディアを現実にすることもできるだろう。一般的に言って、実際にコーディングする以外に、何かを理解するためにより良い方法はあるのだろうか? 6 | -------------------------------------------------------------------------------- /key_generation/key_generation.md: -------------------------------------------------------------------------------- 1 | 4 | # 鍵生成と暗号化 {#key-generation-encryption} 5 | 8 | ## それは本当にランダムだろうか? {#is-it-random-enough} 9 | 12 | 13 | **new Key()** でコンストラクターを呼び出すと、内部ではPRNG(疑似乱数生成器)を使って秘密鍵を生成している。WindowsOS上では、Windows Crypto APIの.Netラッパーである **RNGCryptoServiceProvider** を使用している。 14 | 15 | 18 | アンドロイドでは、私は **SecureRandom** を使用する。実際は **RandomUtils.Random** を使って自分独自の実装を使うことができる。 19 | 20 | 23 | iOS上では、私はまだ実装したことはないが、自分で **IRandom** の実装クラスを作る必要がある。 24 | 25 | 28 | コンピューターにとってランダムにすることは難しい。しかし、1番大きな問題は、ある一連の数値が本当にランダムかどうかを知ることが不可能だということである。 29 | 30 | 33 | もし、マルウェアがあなたのPRNGを改ざんした場合(そうすると、あなたが生成する数値を予測できる)、手遅れになって初めて改ざんされたことに気づくことになる。 34 | 35 | 38 | これは、クロスプラットフォームもしくはネイティブ実装のPRNG(コンピュータのクロックとCPUのスピードの組み合わせを利用)は危険であることを意味する。しかし、手遅れになるまで、それを知る由はない。 39 | 40 | 43 | パフォーマンス上の理由から ほとんどのPRNGは同じように機能する。**シード** とよばれるランダムな数値が1つ選ばれ、呼び出す度に、結果が予測可能な式によって次の値が生成される。 44 | 45 | 48 | シードのランダムさの度合は、**エントロピー** と呼ばれる計測値で定義されるが、エントロピー度は、監視している人にも依存する。 49 | 50 | 54 | 例えば、あなたが自分のクロック時間をもとにシード値を生成したとしよう。 55 | そして、クロックが1ミリ秒の精度を持ったとしよう。(現実には15ミリ秒以上。) 56 | 57 | 61 | もしあなたが先週鍵を生成したと、攻撃者が知っているとすると、シード値は、 62 | 1000 \* 60 \* 60 \* 24 \* 7 = 604800000 通りある。 63 | 64 | 67 | そのような攻撃者にとって、エントロピーは、log2(604800000) = 29.17 ビットである。 68 | 69 | 72 | その程度の回数だと順番に処理するとして、私の自宅のコンピュータで処理させても2秒以下しかかからない。このように順番に全可能性を当たってみる処理のことを”総当たり式”と呼ぶ。 73 | 74 | 78 | でも、例えば、シード値を生成するのに、クロック時間とプロセスIDを使ったとする。 79 | そして、1024個の個別のプロセスIDが存在すると想像してみよう。 80 | 81 | 85 | 今度は、攻撃者は、604800000 \* 1024 回を順番に当たっていく必要があり、それには2000秒かかる。 86 | さて、ここに、コンピューターを起動した日時の情報も足してみよう。攻撃者は私が今日起動したと知っているとしても、86400000 通りの可能性が追加できる。 87 | 88 | 92 | これで、攻撃者は、604800000 \* 1024 \* 86400000 = 5,35088E+19通りの可能性に当たる必要がある。 93 | しかし、覚えておいてほしいのは、もし攻撃者が私のコンピューターに侵入可能であれば、この追加の情報を取得できるので、可能性の数を減らし、エントロピーを下げることができる。 94 | 95 | 98 | エントロピーは、log2(数値の取りえる可能性の数)で計算できるので、log2(5,35088E+19)= 65 ビットとなる。 99 | 100 | 103 | これは十分だろうか。攻撃者が可能性を左右する情報をこれ以上持っていないと仮定するならば、多分そうだろう。 104 | 105 | 108 | しかし、公開鍵のハッシュ値が20バイト = 160ビット ということは、すべてのアドレスの数よりまだ小さい。もう少し頑張れるかもしれない。 109 | 110 | 113 | > **注意:** エントロピーを増やすことは線形的に難しいが、エントロピーを解読するのは、指数関数的に難しくなる。 114 | 115 | 118 | エントロピーを生成する面白い方法は、人間を介在させるやり方だ。(マウスを動かす。) 119 | 120 | 123 | もし、あなたがプラットフォームのPRNGを完全に信頼できない(それはそれほど[おかしな事ではない](http://android-developers.blogspot.fr/2013/08/some-securerandom-thoughts.html))なら、NBitcoinが使用するPRNGからの出力に対して、エントロピーを足すことができる。 124 | 125 | ```cs 126 | RandomUtils.AddEntropy("hello"); 127 | RandomUtils.AddEntropy(new byte[] { 1, 2, 3 }); 128 | var nsaProofKey = new Key(); 129 | ``` 130 | 133 | あなたが **AddEntropy(data)** を呼び出すときNBitcoinが処理するのは、 134 | **additionalEntropy = SHA(SHA(data) ^ additionalEntropy)** だ。 135 | 136 | 139 | そして、新しい数値を取得するときの結果は: 140 | **result = SHA(PRNG() ^ additionalEntropy)** だ。 141 | 142 | 145 | ## 鍵導出関数 {#key-derivation-function} 146 | 149 | しかし、最も重要なことは、可能性の数の多さではなく、攻撃者があなたの鍵を破ることに成功するのに、どれくらいの時間が必要かということである。そこでKDFの登場である。 150 | 151 | 154 | KDF もしくは **鍵導出関数(Key Derivation Function)** が、たとえエントロピーが低くても、より強い鍵をもつための方法である。 155 | 156 | 160 | シード値を生成してみたいと想像してみよう。そして攻撃者が1千万個の可能性があることを知っていたとする。 161 | そのようなシードであれば通常、クラックして破るのは非常に簡単だ。 162 | 167 | 168 | しかし、もしあなたがその順番処理を遅くすることができたとしたらどうだろう? 169 | KDFはハッシュ関数で意図的にコンピューターの演算リソースを無駄に使わせることができる。 170 | これが例だ: 171 | 172 | ```cs 173 | var derived = SCrypt.BitcoinComputeDerivedKey("hello", new byte[] { 1, 2, 3 }); 174 | RandomUtils.AddEntropy(derived); 175 | ``` 176 | 179 | もし仮に、攻撃者があなたのエントロピーの元が5つの文字だと知っていたとしても、Scryptを実行して合っているか可能性を確認しないといけない。私のコンピューターでは5秒かかる。 180 | 181 | 184 | 結局のところ、どういうことかというと、疑似乱数発生器に悪さをされる事を極端に心配する必要はない。エントロピーの増加とKDFの使用、両方をすることで攻撃を弱めることができる。 185 | 189 | 覚えておいてほしいのは攻撃者は、あなたもしくはあなたのシステムの情報を集めることで、エントロピーを減らすことができるということだ。 190 | もし、タイムスタンプを元にエントロピーを作るとして、あなたが先週キーを生成し、しかも午前9時から午後6時までしかコンピューターを使用しないということを攻撃者が知ってしまうと、エントロピーを減らすことになる。 191 | 192 | 195 | 前段で、特別なKDFである**Scrypt**について話した。そこで言ったとおり、KDFの目的は 総当たり攻撃をコストがかかるものにすることだ。 196 | 197 | 200 | なので、KDFを使ってパスワードで、秘密鍵を暗号化する標準の方法がすでにあるとしても、別に驚くことではないだろう。それが、[BIP38](http://www.codeproject.com/Articles/775226/NBitcoin-Cryptography-Part)だ。 201 | 202 | ![](../assets/EncryptedKey.png) 203 | 204 | ```cs 205 | var privateKey = new Key(); 206 | var bitcoinPrivateKey = privateKey.GetWif(Network.Main); 207 | Console.WriteLine(bitcoinPrivateKey); // L1tZPQt7HHj5V49YtYAMSbAmwN9zRjajgXQt9gGtXhNZbcwbZk2r 208 | BitcoinEncryptedSecret encryptedBitcoinPrivateKey = bitcoinPrivateKey.Encrypt("password"); 209 | Console.WriteLine(encryptedBitcoinPrivateKey); // 6PYKYQQgx947Be41aHGypBhK6TA5Xhi9TdPBkatV3fHbbKrdDoBoXFCyLK 210 | var decryptedBitcoinPrivateKey = encryptedBitcoinPrivateKey.GetSecret("password"); 211 | Console.WriteLine(decryptedBitcoinPrivateKey); // L1tZPQt7HHj5V49YtYAMSbAmwN9zRjajgXQt9gGtXhNZbcwbZk2r 212 | 213 | Console.ReadLine(); 214 | ``` 215 | 218 | 219 | このような暗号化は、2つのケースで使用される。: 220 | 221 | 225 | * 鍵の保存場所の提供者を信用していない。(ハッキングされるかもしれないから。) 226 | * 他の人のために鍵を保存しようとしている。(あなたはその人の鍵を知りたくない。) 227 | 228 | 231 | もし、自分のストレージを持っているならデータベースが提供する暗号化で十分だろう。 232 | 233 | 236 | もし、あなたのサーバーが復号化の機能を持つ場合、気を付けなければいけない。もしかすると、攻撃者が大量の鍵を復号化させるようなDDOS攻撃を仕掛けてくるかもしれないからだ。 237 | 238 | 241 | 可能であるならば、復号化は最終利用者に移譲すべきである。 242 | 243 | 246 | ## 古き良き時代のように {#like-the-good-ol-days} 247 | 248 | 252 | まず最初に、なぜ複数の鍵を生成しなければならないのだろうか。 253 | 一番の理由はプライバシーである。すべてのアドレスの残高を、だれでも見ることができるのだから、取引ごとに新しいアドレスを使う方が良い。 254 | 255 | 258 | しかし、実際のところ、相手ごとにも鍵を生成することもできる。それにより、支払元を簡単に特定でき、プライバシーの露出も防げる。 259 | 260 | 263 | これまでのコードでもやってきたように、以下のように鍵を生成できる: 264 | ```cs 265 | var privateKey = new Key() 266 | ``` 267 | 270 | しかし、これには、2つの問題がある: 271 | 272 | 276 | * 新しい鍵を生成することで、自分の持つウォレットのバックアップが古くて使えなってしまう。 277 | * アドレスの作成処理を信用できない相手に委譲することができなくなる。 278 | 279 | 282 | もし、ウェブウォレットを開発していて、ユーザーのためにキーを生成している場合、あるユーザーの鍵が破られたとすると、即座にその人はあなたを疑い始めるだろう。 283 | 284 | 287 | ## BIP38 (パート2) {#bip38-part-2} 288 | 291 | 我々はBIP38をすでに見ているが、実は、このBIPは、2つのアイディアを1つにしたものだ。 292 | 293 | 296 | 2つ目については、どうやって鍵とアドレスの生成を、信頼できない相手に委譲することができるかを書いている。なので、2つの懸念点のうちの1つを解決する。 297 | 298 | 301 | **そのアイディアとは、鍵生成をする人へ渡すパスフレーズコードを作るというものだ。このパスフレーズコードで、その相手はあなたのために、暗号化された鍵を作ることができ、しかも、あなたのパスワードも秘密鍵も知ることはない。** 302 | 303 | この **パスフレーズコード** は WIFフォーマットにして鍵生成する人に渡すことができる。 304 | 305 | 308 | > **注釈**: NBitcoinでは、Bitcoinが頭についている型は全て Base58 (WIF)フォーマットのデータである。 309 | 310 | 313 | なので、鍵の生成を委譲したいユーザーとして最初に、 **パスフレーズコード** を作ることになる。 314 | 315 | ![](../assets/PassphraseCode.png) 316 | 317 | ```cs 318 | var passphraseCode = new BitcoinPassphraseCode("my secret", Network.Main, null); 319 | ``` 320 | 323 | **そしてこのパスフレーズコードを鍵を生成するサードパーティに渡す。** 324 | 325 | 328 | そのサードパーティは、暗号化された鍵をあなたに作ってくれる。 329 | 330 | ![](../assets/PassphraseCodeToEncryptedKeys.png) 331 | 332 | ```cs 333 | EncryptedKeyResult encryptedKeyResult = passphraseCode.GenerateEncryptedSecret(); 334 | ``` 335 | 338 | この **暗号化された鍵** は、たくさんの情報を持っている。 339 | 340 | ![](../assets/EncryptedKeyResult.png) 341 | 342 | 345 | まずは、生成されたビットコインアドレス。 346 | ```cs 347 | var generatedAddress = encryptedKeyResult.GeneratedAddress; // 14KZsAVLwafhttaykXxCZt95HqadPXuz73 348 | ``` 349 | 352 | それから、暗号化された鍵自体(前段で述べた **鍵の暗号化** のレッスンでみたように)。 353 | ```cs 354 | var encryptedKey = encryptedKeyResult.EncryptedKey; // 6PnWtBokjVKMjuSQit1h1Ph6rLMSFz2n4u3bjPJH1JMcp1WHqVSfr5ebNS 355 | ``` 356 | 359 | そして、最後だけれども重要である **確認コード**。これにより、その第三者は、生成された鍵とアドレスが あなたのパスワードに対応していることを証明することができる。 360 | ```cs 361 | var confirmationCode = encryptedKeyResult.ConfirmationCode; // cfrm38VUcrdt2zf1dCgf4e8gPNJJxnhJSdxYg6STRAEs7QuAuLJmT5W7uNqj88hzh9bBnU9GFkN 362 | ``` 363 | 366 | あなたは所有者として、この情報を手に入れたらすぐ、**ConfirmationCode.Check** を使って、鍵作成者がインチキをしていないか確認する必要がある。そして、パスワードを使って秘密鍵を取得する。 367 | 368 | ```cs 369 | Console.WriteLine(confirmationCode.Check("my secret", generatedAddress)); // True 370 | var bitcoinPrivateKey = encryptedKey.GetSecret("my secret"); 371 | Console.WriteLine(bitcoinPrivateKey.GetAddress() == generatedAddress); // True 372 | Console.WriteLine(bitcoinPrivateKey); // KzzHhrkr39a7upeqHzYNNeJuaf1SVDBpxdFDuMvFKbFhcBytDF1R 373 | ``` 374 | 377 | 我々は、第三者がどうやってあなたのパスワードと秘密鍵を知ることなしに暗号化された鍵を作成することができるかを見てきた。 378 | 379 | ![](../assets/ThirdPartyKeyGeneration.png) 380 | 383 | しかし、まだ1つ問題が残っている: 384 | 385 | 388 | * 新しい鍵を生成することで、自分の持つウォレットのバックアップがすべて古いものになってしまう。 389 | 390 | 393 | BIP 32、もしくは 階層的決定性ウォレット(HDウォレット)は、別の解決方法を提案しており、その方がより広くサポートされた方法だ。 394 | 395 | 398 | ## HDウォレット (BIP 32) {#hd-wallet-bip-32} 399 | 402 | それでは、我々が解決したい問題を再度心にとめておこう: 403 | 404 | 408 | * バックアップが古くなってしまうのを防ぎたい 409 | * 信頼してない相手に鍵やアドレスの生成を委譲したい 410 | 411 | 414 | 決定性ウォレットは、バックアップの問題を解決するだろう。そのようなウォレットでは、シード値だけは保存しなければならない。そしてこのシードから、一連の秘密鍵を何度も生成することができる。 415 | 416 | 420 | これが、"決定性"の意味するところである。 421 | 以下のように、マスターキーから新しい鍵をどんどん生成できる。 422 | 423 | ```cs 424 | ExtKey masterKey = new ExtKey(); 425 | Console.WriteLine("Master key : " + masterKey.ToString(Network.Main)); 426 | for (int i = 0; i < 5; i++) 427 | { 428 | ExtKey key = masterKey.Derive((uint)i); 429 | Console.WriteLine("Key " + i + " : " + key.ToString(Network.Main)); 430 | } 431 | ``` 432 | 433 | ``` 434 | Master key : xprv9s21ZrQH143K3JneCAiVkz46BsJ4jUdH8C16DccAgMVfy2yY5L8A4XqTvZqCiKXhNWFZXdLH6VbsCsqBFsSXahfnLajiB6ir46RxgdkNsFk 435 | Key 0 : xprv9tvBA4Kt8UTuEW9Fiuy1PXPWWGch1cyzd1HSAz6oQ1gcirnBrDxLt8qsis6vpNwmSVtLZXWgHbqff9rVeAErb2swwzky82462r6bWZAW6Ty 436 | Key 1 : xprv9tvBA4Kt8UTuHyzrhkRWh9xTavFtYoWhZTopNHGJSe3KomssRrQ9MTAhVWKFp4d7D8CgmT7TRzauoAZXp3xwHQfxr7FpXfJKpPDUtiLdmcF 437 | Key 2 : xprv9tvBA4Kt8UTuLoEZPpW9fBEzC3gfTdj6QzMp8DzMbAeXgDHhSMmdnxSFHCQXycFu8FcqTJRm2kamjeE8CCKzbiXyoKWZ9ihiF7J5JicgaLU 438 | Key 3 : xprv9tvBA4Kt8UTuPwJQyxuZoFj9hcEMCoz7DAWLkz9tRMwnBDiZghWePdD7etfi9RpWEWQjKCM8wHvKQwQ4uiGk8XhdKybzB8n2RVuruQ97Vna 439 | Key 4 : xprv9tvBA4Kt8UTuQoh1dQeJTXsmmTFwCqi4RXWdjBp114rJjNtPBHjxAckQp3yeEFw7Gf4gpnbwQTgDpGtQgcN59E71D2V97RRDtxeJ4rVkw4E 440 | Key 5 : xprv9tvBA4Kt8UTuTdiEhN8iVDr5rfAPSVsCKpDia4GtEsb87eHr8yRVveRhkeLEMvo3XWL3GjzZvncfWVKnKLWUMNqSgdxoNm7zDzzD63dxGsm 441 | ``` 442 | 445 | **マスターキー** だけを保存する必要がある。なぜなら、同じ一連の秘密鍵を何度も生成できるからである。 446 | 447 | 450 | 見ればわかるように、これらの鍵は、 **ExtKey** であり、使い慣れた **Key** ではない。しかし、内部に本物の秘密鍵を内包しているので、使うのを躊躇する必要はない。 451 | 452 | ![](../assets/ExtKey.png) 453 | 456 | 457 | **Key** と **ChainCode** を **ExtKey** のコンストラクターに渡すことで **Key** から **ExtKey** に戻すことも可能である。以下のようにする: 458 | 459 | ```cs 460 | ExtKey extKey = new ExtKey(); 461 | byte[] chainCode = extKey.ChainCode; 462 | Key key = extKey.PrivateKey; 463 | 464 | ExtKey newExtKey = new ExtKey(key, chainCode); 465 | ``` 466 | 467 | 470 | **base58** 型の **ExtKey** は、 **BitcoinExtKey** という。 471 | 472 | 475 | しかし、どうやって2つ目の問題を解決するのだろう: 潜在的にハッキングされる可能性のある相手(支払いサーバー)にアドレスの作成を委譲するには? 476 | 477 | 480 | トリックは、マスターキーの無性化ができるということである。そして、秘密鍵を持たない公開可能なバージョンのマスターキーを持つことができる。無性化されたマスターキーから、第三者機関は、秘密鍵なしに公開鍵を作成できるのだ。 481 | 482 | ```cs 483 | ExtPubKey masterPubKey = masterKey.Neuter(); 484 | for (int i = 0 ; i < 5 ; i++) 485 | { 486 | ExtPubKey pubkey = masterPubKey.Derive((uint)i); 487 | Console.WriteLine("PubKey " + i + " : " + pubkey.ToString(Network.Main)); 488 | } 489 | ``` 490 | 491 | ``` 492 | PubKey 0 : xpub67uQd5a6WCY6A7NZfi7yGoGLwXCTX5R7QQfMag8z1RMGoX1skbXAeB9JtkaTiDoeZPprGH1drvgYcviXKppXtEGSVwmmx4pAdisKv2CqoWS 493 | PubKey 1 : xpub67uQd5a6WCY6CUeDMBvPX6QhGMoMMNKhEzt66hrH6sv7rxujt7igGf9AavEdLB73ZL6ZRJTRnhyc4BTiWeXQZFu7kyjwtDg9tjRcTZunfeR 494 | PubKey 2 : xpub67uQd5a6WCY6Dxbqk9Jo9iopKZUqg8pU1bWXbnesppsR3Nem8y4CVFjKnzBUkSVLGK4defHzKZ3jjAqSzGAKoV2YH4agCAEzzqKzeUaWJMW 495 | PubKey 3 : xpub67uQd5a6WCY6HQKya2Mwwb7bpSNB5XhWCR76kRaPxchE3Y1Y2MAiSjhRGftmeWyX8cJ3kL7LisJ3s4hHDWvhw3DWpEtkihPpofP3dAngh5M 496 | PubKey 4 : xpub67uQd5a6WCY6JddPfiPKdrR49KYEuXUwwJJsL5rWGDDQkpPctdkrwMhXgQ2zWopsSV7buz61e5mGSYgDisqA3D5vyvMtKYP8S3EiBn5c1u4 497 | ``` 498 | 501 | では、支払いサーバーが公開鍵1を生成したと想定してみよう。すると対応した秘密鍵を、秘密のマスターキーを使って得ることができる。 502 | ```cs 503 | masterKey = new ExtKey(); 504 | masterPubKey = masterKey.Neuter(); 505 | 506 | //The payment server generate pubkey1 507 | ExtPubKey pubkey1 = masterPubKey.Derive((uint)1); 508 | 509 | //You get the private key of pubkey1 510 | ExtKey key1 = masterKey.Derive((uint)1); 511 | 512 | //Check it is legit 513 | Console.WriteLine("Generated address : " + pubkey1.PubKey.GetAddress(Network.Main)); 514 | Console.WriteLine("Expected address : " + key1.PrivateKey.PubKey.GetAddress(Network.Main)); 515 | ``` 516 | 517 | ``` 518 | Generated address : 1Jy8nALZNqpf4rFN9TWG2qXapZUBvquFfX 519 | Expected address : 1Jy8nALZNqpf4rFN9TWG2qXapZUBvquFfX 520 | ``` 521 | 524 | **ExtPubKey** は **ExtKey** に似ている。が、両者の違いは、 **PubKey** (公開鍵)を保持しているが **Key** (秘密鍵)は保持していない。 525 | 526 | 527 | 528 | ![](../assets/ExtPubKey.png) 529 | 530 | 533 | ここまで、決定性鍵がどうやって問題を解決してくれるのかを見てきた。では、次は、 **階層的** が何を意味するかについて議論してみよう。 534 | 535 | 538 | 前段の演習では、マスターキーとインデックス番号の組み合わせにより 鍵を生成するのを見てきた。このプロセスを **派生** と呼び、マスターキーは **親の鍵** で、生成される鍵は、**子供の鍵** である。 539 | 540 | 543 | しかし、子供の鍵から派生した、さらに子供の鍵を複数作ることができる。これが **階層的** の意味である。 544 | 545 | 548 | なので、概念的かつ一般的にこのように言うことができる: 親の鍵 + 鍵の階層パス → 子供の鍵 549 | 550 | ![](../assets/Derive1.png) 551 | 552 | ![](../assets/Derive2.png) 553 | 554 | 557 | この図に書かれているように、親から2つのやり方で子供(1,1)を派生させることができる。 558 | ```cs 559 | ExtKey parent = new ExtKey(); 560 | ExtKey child11 = parent.Derive(1).Derive(1); 561 | ``` 562 | 563 | もしくは、 564 | 565 | ```cs 566 | ExtKey parent = new ExtKey(); 567 | ExtKey child11 = parent.Derive(new KeyPath("1/1")); 568 | ``` 569 | 572 | なので、まとめると: 573 | 574 | ![](../assets/DeriveKeyPath.png) 575 | 576 | 579 | **ExtPubKey** も同じように取り扱うことができる。 580 | 581 | 584 | なぜ 階層的な鍵が必要になるのだろう?なぜなら、自分の複数の口座のための鍵を目的に別に分類するのは、良い方法だと思われるからだ。詳しくは、[BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)。 585 | 586 | 589 | そして、 組織の内部において口座の権限を分けて管理することができるようにもなる。 590 | 591 | 594 | 自分をある会社のCEOだとしてみよう。すると、会社のウォレットをすべて管理したいだろう。しかし、経理部に、マーケティング部のお金を使ってほしくない。 595 | 596 | 599 | すると最初に思いつくアイディアは、1つの部署に1つの階層を生成することだろう。 600 | 601 | ![](../assets/CeoMarketingAccounting.png) 602 | 603 | 606 | しかし、この場合、**経理部** と **マーケティング部** はCEOの秘密鍵を逆生成できるかもしれない。 607 | 608 | 611 | そのような子供鍵は **非強化** であると言われる。 612 | 613 | ![](../assets/NonHardened.png) 614 | 615 | ```cs 616 | ExtKey ceoKey = new ExtKey(); 617 | Console.WriteLine("CEO: " + ceoKey.ToString(Network.Main)); 618 | ExtKey accountingKey = ceoKey.Derive(0, hardened: false); 619 | 620 | ExtPubKey ceoPubkey = ceoKey.Neuter(); 621 | 622 | //Recover ceo key with accounting private key and ceo public key 623 | ExtKey ceoKeyRecovered = accountingKey.GetParentExtKey(ceoPubkey); 624 | Console.WriteLine("CEO recovered: " + ceoKeyRecovered.ToString(Network.Main)); 625 | ``` 626 | 627 | ``` 628 | CEO: xprv9s21ZrQH143K2XcJU89thgkBehaMqvcj4A6JFxwPs6ZzGYHYT8dTchd87TC4NHSwvDuexuFVFpYaAt3gztYtZyXmy2hCVyVyxumdxfDBpoC 629 | CEO recovered: xprv9s21ZrQH143K2XcJU89thgkBehaMqvcj4A6JFxwPs6ZzGYHYT8dTchd87TC4NHSwvDuexuFVFpYaAt3gztYtZyXmy2hCVyVyxumdxfDBpoC 630 | ``` 631 | 634 | 別の言い方でいうと、 **非強化鍵** は階層を"登る"ことができる。**非強化鍵** は単一管理されるタイプの口座にだけ使用されるべきでる。 635 | 636 | 639 | なので、我々のケースでは、CEOは **強化鍵** を作成しなければならない。そうすれば、経理部は、階層を登って秘密鍵を見つけることはできない。 640 | 641 | ```cs 642 | ExtKey ceoKey = new ExtKey(); 643 | Console.WriteLine("CEO: " + ceoKey.ToString(Network.Main)); 644 | ExtKey accountingKey = ceoKey.Derive(0, hardened: true); 645 | 646 | ExtPubKey ceoPubkey = ceoKey.Neuter(); 647 | 648 | ExtKey ceoKeyRecovered = accountingKey.GetParentExtKey(ceoPubkey); //Crash 649 | ``` 650 | 651 | 654 | **ExtKey.Derivate**(**鍵階層パス)** を使うときに、子のインデックス値の後ろにアポストロフィを付けることでも、強化鍵を作成できる。 655 | 656 | ```cs 657 | var nonHardened = new KeyPath("1/2/3"); 658 | var hardened = new KeyPath("1/2/3'"); 659 | ``` 660 | 663 | では経理部は、顧客ごとに1つの親鍵を生成したと想定してみよう。そして、顧客からの支払いごとにその子供鍵を使う。 664 | 665 | 668 | CEOであるあなたは、そのうちの1つのアドレスから支払いたい場合、こうやって行う。 669 | 670 | ```cs 671 | ceoKey = new ExtKey(); 672 | string accounting = "1'"; 673 | int customerId = 5; 674 | int paymentId = 50; 675 | KeyPath path = new KeyPath(accounting + "/" + customerId + "/" + paymentId); 676 | //Path : "1'/5/50" 677 | ExtKey paymentKey = ceoKey.Derive(path); 678 | ``` 679 | 680 | 683 | ## HD鍵のためのネモニック(記憶しやすい)コード(BIP39){#mnemonic-code-for-hd-keys-bip39} 684 | 687 | これまで見たように、HD鍵を作成することは簡単である。しかしもし、そんな鍵を電話や手書きで人に伝える簡単な方法があればどうだろうか? 688 | 689 | 692 | Tresorのようなコールドウォレットは、簡単に書き留められるようなある文章をもとに、HD鍵を生成する。そういった文章は **ザ・シード** と言われたり **ネモニック(記憶文)** と言われる。そして、それはパスワードやPIN番号でさらに暗号化される。 693 | 694 | ![](../assets/Trezor.png) 695 | 696 | 699 | 書き留めやすい文章を生成するために使用される言葉は、**単語リスト** と呼ばれる。 700 | 701 | ![](../assets/RootKey.png) 702 | ```cs 703 | Mnemonic mnemo = new Mnemonic(Wordlist.English, WordCount.Twelve); 704 | ExtKey hdRoot = mnemo.DeriveExtKey("my password"); 705 | Console.WriteLine(mnemo); 706 | ``` 707 | 708 | ```minute put grant neglect anxiety case globe win famous correct turn link``` 709 | 710 | 713 | 714 | ここでもし、ネモニックとパスワードを持っていたら、 **階層ルート** の鍵を見つけることができる。 715 | 716 | ```cs 717 | mnemo = new Mnemonic("minute put grant neglect anxiety case globe win famous correct turn link", 718 | Wordlist.English); 719 | hdRoot = mnemo.DeriveExtKey("my password"); 720 | ``` 721 | 724 | 現時点でサポートされている **単語リスト** の言語は、英語、日本語、スペイン語、中国語(簡体字と繁体字)である。 725 | 726 | 729 | ## ダークウォレット {#dark-wallet} 730 | 731 | 734 | この名前がついたのは不運である。なぜなら、まったくもってこのウォレットはダークではないのに、不要な注目や懸念を生んでしまっている。ダークウォレットは、我々の最初の2つの問題に対する実践的な解決策である。 735 | 736 | 740 | * 古くなって使えなくなるウォレットのバックアップを防ぐ 741 | * 鍵とアドレスの生成を信用していない相手に移譲すること 742 | 743 | 746 | しかし、このウォレットは、ボーナス的なすごい機能をもつのだ。 747 | 748 | 751 | あなたは、唯一の( **ステルスアドレス** と呼ばれる)アドレスだけを、ほかの人たちにシェアするだけでよいのだ。よって、プライバシーを失うことがない。 752 | 753 | 756 | ここで思い出してほしいのは、1つの **ビットコインアドレス** をみんなと共有すると、すべての人たちは、ブロックチェーンをみれば、あなたの持っているビットコインの残高を知ることができるということだ。しかし、**ステルスアドレス** を使えば、それには当たらない。 757 | 758 | 761 | このウォレットがダークと命名されたのは、本当に残念なことである。なぜかというと、それは部分的にでもビットコインの疑似匿名性が原因として起きる、プライバシー問題を解決するからである。より良い名前があるとしたら、**ワン・アドレス** だったかもしれない。 762 | 763 | 766 | ダークウォレットの用語を使うと、以下のように参加者を表現する: 767 | 768 | 773 | * **支払者** は、 **受領者** の **ステルスアドレス** を知っている。 774 | * **受領者** は、 **スペンド鍵** を知っていて、その秘密のコードで彼が受け取るコインを消費することができる。 775 | * **スキャナー** は、**スキャン鍵** を知っていて、 その秘密のコードで、 その **受領者** に属する取引を特定することができる。 776 | 777 | 780 | 以降は、操作の詳細になる。内部的には、このステルスアドレスは、1つもしくは複数(複数署名の場合)の **スペンド公開鍵** と1つの **スキャン公開鍵** で構成されている。 781 | 782 | ![](../assets/StealthAddress.png) 783 | 784 | ```cs 785 | var scanKey = new Key(); 786 | var spendKey = new Key(); 787 | BitcoinStealthAddress stealthAddress 788 | = new BitcoinStealthAddress 789 | ( 790 | scanKey: scanKey.PubKey, 791 | pubKeys: new[] { spendKey.PubKey }, 792 | signatureCount: 1, 793 | bitfield: null, 794 | network: Network.Main); 795 | ``` 796 | 799 | **支払者** は、あなたの **ステルスアドレス** を使って、一時的に使用する **エフェム鍵** を作成し、そこから **ステルス公開鍵** を生成する。それから、支払いが行われるビットコインアドレスが作成される。 800 | 801 | ![](../assets/EphemKey.png) 802 | 803 | 806 | そして、(最初のチャレンジでやったように)トランザクションのOP_RETURNに埋め込まれた **ステルスメタデータ** の中に **エフェム公開鍵** をパッケージする。 807 | 808 | 811 | さらに、トランザクション・アウトプットを生成されたビットコインアドレス( **ステルス公開鍵** のアドレス)へ追加する。 812 | 813 | ![](../assets/StealthMetadata.png) 814 | 815 | ```cs 816 | var ephemKey = new Key(); 817 | Transaction transaction = new Transaction(); 818 | stealthAddress.SendTo(transaction, Money.Coins(1.0m), ephemKey); 819 | Console.WriteLine(transaction); 820 | ``` 821 | 824 | **エフェム鍵** の生成の実装については詳細すぎるので、無視して良いだろう。NBitcoinが自動的に生成してくれる: 825 | 826 | ```cs 827 | Transaction transaction = new Transaction(); 828 | stealthAddress.SendTo(transaction, Money.Coins(1.0m)); 829 | Console.WriteLine(transaction); 830 | ``` 831 | 832 | ```json 833 | { 834 | "hash": "7772b0ad19acd1bd2b0330238a898fe021486315bd1e15f4154cd3931a4940f9", 835 | "ver": 1, 836 | "vin_sz": 0, 837 | "vout_sz": 2, 838 | "lock_time": 0, 839 | "size": 93, 840 | "in": [], 841 | "out": [ 842 | { 843 | "value": "0.00000000", 844 | "scriptPubKey": "OP_RETURN 060000000002b9266f15e8c6598e7f25d3262969a774df32b9b0b50fea44fc8d914c68176f3e" 845 | }, 846 | { 847 | "value": "1.00000000", 848 | "scriptPubKey": "OP_DUP OP_HASH16051f68af989f5bf24259c519829f46c7f2935b756 OP_EQUALVERIFY OP_CHECKSIG" 849 | } 850 | ] 851 | } 852 | ``` 853 | 856 | そして、支払者は、トランザクション・インプットをトランザクションに追加し署名をする。それからビットコインネットワークにトランザクションを送信する。 857 | 858 | 861 | **ステルスアドレス** と **スキャン鍵** を知る **スキャナー** は、**ステルス公開鍵** を取得できるので、予定された **ビットコインアドレス** への支払いも確認できる。 862 | ![](../assets/ScannerRecover.png) 863 | 864 | 867 | それから **スキャナー** は、トランザクションのアウトプットの1つがそのアドレスに対するものかをチェックし、もしそうであるなら **スキャナー** は、 **受領者** に対してトランザクションについて通知する。 868 | 869 | 872 | **受領者** は、**スペンド鍵** を使うことでそのアドレスの秘密鍵を取得できる。 873 | 874 | ![](../assets/ReceiverStealth.png) 875 | 876 | 879 | スキャナーとして、どうやってトランザクションをスキャンするか、そして受領者としてどうやって秘密鍵を見つけるかについてのコードは、あとの **TransactionBuilderを使ってみる** の章で説明する。 880 | 881 | 884 | ここで知ってほしいのは、**ステルスアドレス** は、複数の **スペンド公開鍵** を持つことができることだ。それを使う場合、そのアドレスはマルチシグ用(複数人による署名)のアドレスということになる。 885 | 886 | 889 | ダークウォレットの唯一の制限事項は、**OP_RETURN** を使用するということである。すなわち、トランザクションに任意のデータを埋め込むことが簡単にはできない。(現在のビットコインのルールでは、OP_RETURNには40バイトしか許されていない。もうすぐ1トランザクションに対して80バイトになる予定だ。) 890 | 891 | 902 | > ([Stackoverflow](http://bitcoin.stackexchange.com/a/29648/26859)) 私が理解するに、"ステルスアドレス"とは、ある特定の問題に対応するために作られた。一般の人々からお金を集めたいと思ったら、例えば寄付のためのアドレスを自分のウェブサイトに載せるとかいうようにだが、そうすると、ブロックチェーン上ですべての支払いの情報が見られてしまう。もしかしたら、あなたがそのアドレスから何に支払ったかを追跡されるだろう。 903 | > 904 | ステルスアドレスを使うケースでは、支払者にユニークなアドレスを生成するように依頼する。そうすることで、そのトランザクションに内包された追加情報を使うだけで、対応した秘密鍵を推測することができる。そしてあなたは、1つのステルスアドレスをウェブサイトに公開したにもかかわらず、ブロックチェーン上では、すべて違ったアドレスに支払いが行われることになり、それぞれアドレスの関連性を見つけることは不可能だ。(もちろん支払者は、支払先アドレスを知っているので、そこからどこにお金を送ったかは見ることができるが、ほかの支払者には、それを見ることができない。) 905 | > 906 | しかし、ほかの方法でも同様の効果を得ることはできる:それぞれの支払者に対して、固有の別々のアドレスを渡せばよい。1つの公開アドレスをウェブサイトに載せる代わりに、例えば押されるごとに新しいアドレスを生成し、秘密鍵を保存するようなボタンを置いておくとか、事前に用意しておいた公開アドレスのリストから次々とアドレスを選んで使うようなボタンを配置するとか(もちろん秘密鍵は、安全な場所に保存しておく)。ステルスアドレスを使用するときと同様に、支払いはすべて個別のアドレスへ行われ、アドレス間の相関は全くないし、一人の支払者が、別の支払情報を見ることもできない。 907 | > 908 | なので、ステルスアドレスを使用することとの唯一の違いは、サーバーが面倒なアドレス作成の処理をしなくて良いということである。実は、ある意味でステルスアドレスを使用するのは悪いことかもしれない。なぜなら、ステルスアドレスを使用する人が少ないため、もしあなたがステルスアドレスを使用していると知られてしまうと、ステルスアドレスのトランザクションは、あなたのものであると分かってしまうからだ。 909 | > 910 | この方法は"100%の匿名性"を提供しない。ビットコインの基本的な匿名性に対する弱さは、残ってしまう。すなわち、だれでも支払いのつながりを見ることができるということだ。なので、もしあなたが、あるトランザクションそのもの、もしくは、そのトランザクションの関係者だと知るならば、そのビットコインがどこからきて、どこへいったのを見ることができるのだ。 911 | -------------------------------------------------------------------------------- /other_types_of_asset/README.md: -------------------------------------------------------------------------------- 1 | # その他のアセットタイプ {#other-types-of-asset} 2 | 3 | 前章では所有権を表すいろいろな種類を見てきた。すべての所有権の表し方とその証明方法を見てきたが、今度はどのようにビットコインを、新しい所有権を発明するためにコードし得るかを理解しよう。 4 | 5 | -------------------------------------------------------------------------------- /other_types_of_asset/colored_coins.md: -------------------------------------------------------------------------------- 1 | ## Colored Coins {#colored-coins} 2 | 3 | 今まではずっと、ネットワーク上でビットコインをどのように交換するかを見てきた。しかしビットコインネットワークは、どんなアセットの種類であっても移動して交換することができる。 4 | 5 | このアセットは「カラードコイン」と呼ばれる。 6 | ビットコインブロックチェーンに関しては、ビットコインとカラードコインにちがいはない。 7 | 8 | カラードコインは標準的な **トランザクションアウトプット** に記録される。ほとんどの場合、この **トランザクションアウトプット** は「Dust」と呼ばれる除去できないビットコインの価値(600satoshi)を含んでいる。 9 | 10 | カラードコインの真の価値は、そのコインの **発行者** がそれと何を交換するつもりかによって決まる。 11 | 12 | ![](../assets/ColoredCoin.png) 13 | 14 | カラードコインは特別な意味を持った普通のコイン以外の何者でもないので、それはつまり今まで所有権の証明や **TransactionBuilder** について見てきたすべてが通用するということだ。今までと同じルールで確実にカラードコインを移動できる。 15 | 16 | ビットコインブロックチェーンに関する限り、**カラードコイン** はほか全て同じように **ビットコイン** なのだ。 17 | 18 | カラードコインによっていろいろなアセットの種類を表現できる。たとえば会社の株、公債や選挙の票などだ。 19 | 20 | しかしどんなアセットを表現しようとしても、いつもそこにはアセットの **発行者** と **所持者** との間で信頼関係があるだろう。 21 | もし会社の株を持っていたとしても、ひょっとすると会社は配当を送らない決定をするかもしれない。 22 | もし公債を持っていたとしても、ひょっとすると銀行は満期になっても交換してくれないかもしれない。 23 | 24 | しかし、契約違反は **Ricardian Contracts** によってもしかしたら自動的に発見されるかもしれない。 25 | **Ricardian Contract** はアセットに付与された権利をもとに、発行者が契約に署名するものだ。このような契約は人間にも読めるし(PDFで)、構造化もされる(jsonで)ので、自動的にどんな違反も証明できるのだ。 26 | **発行者** はアセットに付与された **ricardian contract** を変えることはできない。 27 | 28 | ビットコインブロックチェーンは、財務的な道具の移動媒介に過ぎない。 29 | イノベーションなのは、あらゆる人が仲介人なしに自分自身のアセットを作り、移動できることだ。ところが伝統的なアセット移動のための仲介人(クリアリングハウス)は厳密に規制されたり、意図的に秘匿化され、一般大衆に公にしなかったりするのだ。 30 | 31 | **オープンアセット** は、ビットコインブロックチェーン上でカラードコインを **移動し、発行する** 方法を著したFlavien Charlonによって作られたプロトコルの名前だ。 32 | 他のプロトコルも存在しているが、オープンアセットが最も簡単かつ柔軟で、**NBitcoin** によってサポートされているただ1つのプロトコルだ。 33 | 34 | この本の残りでは、オープンアセットプロトコルの詳細については言及しないつもりだが、GitHub上の仕様書のページが詳細を知るには良いだろう。 35 | -------------------------------------------------------------------------------- /other_types_of_asset/issuing_an_asset.md: -------------------------------------------------------------------------------- 1 | ## 資産の発行 {#issuing-an-asset} 2 | 3 | ### 目的 {#objective} 4 | 5 | このエクササイズのために、**BlockchainProgrammingコイン** を発行しよう。 6 | 7 | 僕に **0.004ビットコイン** を送るごとに **BlockchainProgrammingコイン** を1つ手に入れられる。 8 | もしなにか言葉を添えてもらえると **さらにもう1つ** 手に入れられる。 9 | さらにこれは[成功者の殿堂](http://n.bitcoin.ninja/)に名を連ねる絶好の機会だ。 10 | 11 | どのようにこの特徴をコーディングするか見てみよう。 12 | 13 | ### コインの発行 {#issuance-coin} 14 | 15 | オープンアセットでは、アセットIDが発行者の **scriptPubKey** から引き出される。 16 | もしカラードコインを発行したければ、その **scriptPubKey** の所有権を証明する必要がある。そしてビットコインブロックチェーンでそれをする唯一の方法はその **scriptPubKey** に帰属しているコインを支払いに使うことだ。 17 | 18 | カラードコインを発行するために使うことを選んだコインは **NBitcoin** では「**Issuance Coin**」と呼ぶ。 19 | この本のビットコインアドレス:[1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB](https://www.smartbit.com.au/address/1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB)からアセットを発行したいと思う。 20 | 21 | 僕の残高を見てほしい。アセットを発行するために次のコインを使うことに決めたとしよう。 22 | 23 | ```json 24 | { 25 | "transactionId": "eb49a599c749c82d824caf9dd69c4e359261d49bbb0b9d6dc18c59bc9214e43b", 26 | "index": 0, 27 | "value": 2000000, 28 | "scriptPubKey": "76a914c81e8e7b7ffca043b088a992795b15887c96159288ac", 29 | "redeemScript": null 30 | } 31 | ``` 32 | 33 | こうして僕のissuance coinを作る。 34 | 35 | ```cs 36 | var coin = new Coin( 37 | fromTxHash: new uint256("eb49a599c749c82d824caf9dd69c4e359261d49bbb0b9d6dc18c59bc9214e43b"), 38 | fromOutputIndex: 0, 39 | amount: Money.Satoshis(2000000), 40 | scriptPubKey: new Script(Encoders.Hex.DecodeData("76a914c81e8e7b7ffca043b088a992795b15887c96159288ac"))); 41 | 42 | var issuance = new IssuanceCoin(coin); 43 | ``` 44 | 45 | ここで **TransactionBuilder** の助けを借りて、トランザクションを生成して署名する必要がある。 46 | 47 | ```cs 48 | var nico = BitcoinAddress.Create("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe"); 49 | var bookKey = new BitcoinSecret("???????"); 50 | TransactionBuilder builder = new TransactionBuilder(); 51 | 52 | var tx = builder 53 | .AddKeys(bookKey) 54 | .AddCoins(issuance) 55 | .IssueAsset(nico, new AssetMoney(issuance.AssetId, quantity: 10)) 56 | .SendFees(Money.Coins(0.0001m)) 57 | .SetChange(bookKey.GetAddress()) 58 | .BuildTransaction(true); 59 | 60 | Console.WriteLine(tx); 61 | ``` 62 | 63 | ```json 64 | { 65 | … 66 | "out": [ 67 | { 68 | "value": "0.00000600", 69 | "scriptPubKey": "OP_DUP OP_HASH160 356facdac5f5bcae995d13e667bb5864fd1e7d59 OP_EQUALVERIFY OP_CHECKSIG" 70 | }, 71 | { 72 | "value": "0.01989400", 73 | "scriptPubKey": "OP_DUP OP_HASH160 c81e8e7b7ffca043b088a992795b15887c961592 OP_EQUALVERIFY OP_CHECKSIG" 74 | }, 75 | { 76 | "value": "0.00000000", 77 | "scriptPubKey": "OP_RETURN 4f410100010a00" 78 | } 79 | ] 80 | } 81 | ``` 82 | 83 | トランザクションアウトプットにOP\_RETURNアウトプットを含んでいることがわかるだろう。事実、これがカラードコインについての情報が詰め込まれる場所なのだ。 84 | 85 | ここにOP\_RETURNの中のデータフォーマットを示す。 86 | 87 | ![](../assets/ColorMaker.png) 88 | 89 | 今のケースではカラードコインの数は10だけで、それが`nico`に対して僕が発行したアセットの数だ。Metadataは任意のデータだ。あとの説明で「Asset Definition」を示すURLを示すところだとわかる。 90 | **Asset Definition** はそのアセットが何なのかを表現する文書だ。定義するかどうかは任意なのでここでは使っていない(Ricardian Contractの章でこれに触れる)。 91 | 92 | さらに詳しい説明は [Open Asset Specification](https://github.com/OpenAssets/open-assets-protocol/blob/master/specification.mediawiki)をチェックしてほしい。 93 | 94 | トランザクションの正当性を確認したら、ネットワークに送る準備ができている。 95 | 96 | ```cs 97 | Console.WriteLine(builder.Verify(tx)); 98 | ``` 99 | 100 | ### QBitNinjaを使ってブロードキャスト 101 | 102 | ```cs 103 | var client = new QBitNinjaClient(Network.Main); 104 | BroadcastResponse broadcastResponse = client.Broadcast(tx).Result; 105 | 106 | if (!broadcastResponse.Success) 107 | { 108 | Console.WriteLine("ErrorCode: " + broadcastResponse.Error.ErrorCode); 109 | Console.WriteLine("Error message: " + broadcastResponse.Error.Reason); 110 | } 111 | else 112 | { 113 | Console.WriteLine("Success!"); 114 | } 115 | ``` 116 | 117 | ### ローカルのビットコインコアを使ってブロードキャスト 118 | 119 | ```cs 120 | using (var node = Node.ConnectToLocal(Network.Main)) //Connect to the node 121 | { 122 | node.VersionHandshake(); //Say hello 123 | //Advertize your transaction (send just the hash) 124 | node.SendMessage(new InvPayload(InventoryType.MSG_TX, tx.GetHash())); 125 | //Send it 126 | node.SendMessage(new TxPayload(tx)); 127 | Thread.Sleep(500); //Wait a bit 128 | } 129 | ``` 130 | 131 | 僕のビットコインウォレットは、本のアドレスとNicoのアドレスと両方持っている。 132 | 133 | ![](../assets/NicoWallet.png) 134 | 135 | 見てのとおり、ビットコインコアは僕が払った0.0001BTCの手数料しか表示してくれず、600satoshiのコインは無視している。これはスパムを抑止する機能があるからだ。 136 | 137 | この古典的なビットコインウォレットではカラードコインをまったく認識しない。 138 | さらに悪いことに、古典的なビットコインウォレットでカラードコインを使うと、そこに関連づいているアセットを破壊し、**トランザクションアウトプット** にあるビットコインの価値、つまり600satoshiしか移動しない。 139 | 140 | カラードコインをサポートしていないウォレットにユーザーが送ってしまうことを防止するために、オープンアセットでは独自のアドレスフォーマットがあって、それはカラードコインウォレットしか認識しないようになっている。 141 | 142 | ```cs 143 | nico = BitcoinAddress.Create("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe"); 144 | Console.WriteLine(nico.ToColoredAddress()); 145 | ``` 146 | 147 | ``` 148 | akFqRqfdmAaXfPDmvQZVpcAQnQZmqrx4gcZ 149 | ``` 150 | 151 | いま、Coinprismのようなオープンアセットと互換性のあるウォレットで見てみると、僕のアセットが正しく表示される。 152 | 153 | ![](../assets/Coinprism.png) 154 | 155 | 言ったとおり、アセットIDが発行者の **ScriptPubKey** から引き出されている。ここにコードでアセットIDを得る方法を示す。 156 | 157 | ```cs 158 | var book = BitcoinAddress.Create("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB"); 159 | var assetId = new AssetId(book).GetWif(Network.Main); 160 | Console.WriteLine(assetId); // AVAVfLSb1KZf9tJzrUVpktjxKUXGxUTD4e 161 | ``` 162 | -------------------------------------------------------------------------------- /other_types_of_asset/liquid_democracy.md: -------------------------------------------------------------------------------- 1 | ## 流動体民主主義 {#liquid-democracy} 2 | 3 | ### 概要 {#overview} 4 | 5 | この章は単純にカラードコインの1つのアプリケーションの概念的なエクササイズとなっている。 6 | 7 | 投票の後、投資家によっていくつか決定がなされる会社を想像してほしい。 8 | 9 | * 何人かの投資家はトピックを十分に知らないから、いくつかの議題を他の誰かに委任したいと思っている。 10 | * かなりたくさんの投資家がいる可能性もある。 11 | * CEOとして、会社に資金を提供するために投票権を売れるようにしたい 12 | * CEOとして、決定するときに票を投じることができるようにしたい 13 | 14 | どうやってカラードコインによって、このような投票を透明性を維持したままで行えるようにできるだろうか。 15 | 16 | しかし始める前に、ブロックチェーン上で投票を行うときのいくつかの欠点に触れておきたい。 17 | 18 | * だれも投票者が実際に誰なのかを知らない 19 | * マイナーは投票の内容に気づけてしまうかもしれない(たとえそれが可能であったとして、興味はないと思われるが) 20 | * たとえだれも投票者が実際に誰なのか知らないとしても、いくつかの票を通じた投票者のふるまいに対する分析によって、アイデンティティがひょっとすると明らかになってしまうかもしれない 21 | 22 | これらのポイントが妥当かどうかは、その投票をとりまとめる人の決定次第である。 23 | 24 | どのようにしてそれを実装するか、概要を見てみよう。 25 | 26 | ### 投票権を発行する {#issuing-voting-power} 27 | 28 | すべては投資家に対して会社の「決定ができる権利」を売りたい会社の創設者(ボスと呼ぼう)によって始まる。決定権は、このエクササイズでは「Power Coin」と呼ぶことにするが、カラードコインを形作れる。 29 | 30 | 紫色で表現しよう。 31 | 32 | ![](../assets/PowerCoin.png) 33 | 34 | たとえば3人が興味を持ったとして、その3人をサトシ、アリスとボブとしよう(そう、再登場だ)。 35 | そしてボスはPower Coinを0.1BTCで売ることに決めた。 36 | 37 | `powerCoin`アドレス、`satoshi`、`alice`そして`bob`にビットコインを与えよう。 38 | 39 | ```cs 40 | var powerCoin = new Key(); 41 | var alice = new Key(); 42 | var bob = new Key(); 43 | var satoshi = new Key(); 44 | var init = new Transaction() 45 | { 46 | Outputs = 47 | { 48 | new TxOut(Money.Coins(1.0m), powerCoin), 49 | new TxOut(Money.Coins(1.0m), alice), 50 | new TxOut(Money.Coins(1.0m), bob), 51 | new TxOut(Money.Coins(1.0m), satoshi), 52 | } 53 | }; 54 | 55 | var repo = new NoSqlColoredTransactionRepository(); 56 | repo.Transactions.Put(init); 57 | ``` 58 | 59 | アリスが2つPower coinを買ったことにしよう。ここにそのトランザクションの作り方を示す。 60 | 61 | ![](../assets/Power2Alice.png) 62 | 63 | ```cs 64 | var issuance = GetCoins(init,powerCoin) 65 | .Select(c=> new IssuanceCoin(c)) 66 | .ToArray(); 67 | var builder = new TransactionBuilder(); 68 | var toAlice = 69 | builder 70 | .AddCoins(issuance) 71 | .AddKeys(powerCoin) 72 | .IssueAsset(alice, new AssetMoney(powerCoin, 2)) 73 | .SetChange(powerCoin) 74 | .Then() 75 | .AddCoins(GetCoins(init, alice)) 76 | .AddKeys(alice) 77 | .Send(alice, Money.Coins(0.2m)) 78 | .SetChange(alice) 79 | .BuildTransaction(true); 80 | repo.Transactions.Put(toAlice); 81 | ``` 82 | 83 | 要約すると、powerCoinは2つのPower Coinをアリスに発行し、お釣りを自身に送っている。同様にアリスは0.2BTCをpowerCoinに送り、そのお釣りを自身に返す。 84 | 85 | **GetCoins**はこのようになっている。 86 | 87 | ```cs 88 | private IEnumerable GetCoins(Transaction tx, Key owner) 89 | { 90 | return tx.Outputs.AsCoins().Where(c => c.ScriptPubKey == owner.ScriptPubKey); 91 | } 92 | ``` 93 | 94 | 理由があってアリスはひょっとするとサトシに投票権のいくつかを売りたくなるかもしれない。 95 | 96 | ![](../assets/PowerCoin2.png) 97 | 98 | **init**トランザクションからアリスのコインをダブルスペンドしていることがわかるだろう。 99 | _\*\*これはビットコインブロックチェーンでは受け入れられないだろう。しかしまだブロックチェーンから簡単に使われていないコインを引き出す方法を見ていないから、エクササイズではコインはダブルスペンドされていなかったと仮定しよう。_ 100 | 101 | 今、アリスとサトシが投票権を持っている。どのようにしてボスが投票をさせるか見てみよう。 102 | 103 | ### 投票の実施 {#running-a-vote} 104 | 105 | ブロックチェーンを調べれば、ボスはいつでもPower Coinを持っている**ScriptPubKey**を知ることができる。 106 | そしてボスはPower Coinを持っている人に、その投票権に比例したVoting Coinを送る。このケーススタディーではアリスに1voting coin、サトシに1voting coin送ることとしよう。 107 | 108 | ![](../assets/PowerCoin3.png) 109 | 110 | 最初に**votingCoin**に対してビットコインを付与する必要がある。 111 | 112 | ```cs 113 | var votingCoin = new Key(); 114 | var init2 = new Transaction() 115 | { 116 | Outputs = 117 | { 118 | new TxOut(Money.Coins(1.0m), votingCoin), 119 | } 120 | }; 121 | repo.Transactions.Put(init2); 122 | ``` 123 | 124 | そしてvoting coinを発行する。 125 | 126 | ```cs 127 | issuance = GetCoins(init2, votingCoin).Select(c => new IssuanceCoin(c)).ToArray(); 128 | builder = new TransactionBuilder(); 129 | var toVoters = 130 | builder 131 | .AddCoins(issuance) 132 | .AddKeys(votingCoin) 133 | .IssueAsset(alice, new AssetMoney(votingCoin, 1)) 134 | .IssueAsset(satoshi, new AssetMoney(votingCoin, 1)) 135 | .SetChange(votingCoin) 136 | .BuildTransaction(true); 137 | repo.Transactions.Put(toVoters); 138 | ``` 139 | 140 | ### 投票の委任 {#vote-delegation} 141 | 142 | 問題は、投票はビジネスの財務的な側面にも議題が及んでおり、アリスは主にマーケティングの側面に関心があるということだ。 143 | 144 | アリスは、財務的な問題に関して、自分よりも良い判断をすると信頼している誰かに投票権を譲渡することに決めた。彼女はボブを委任相手に選んだ。 145 | 146 | ![](../assets/PowerCoin4.png) 147 | 148 | ```cs 149 | var aliceVotingCoin = ColoredCoin.Find(toVoters,repo) 150 | .Where(c=>c.ScriptPubKey == alice.ScriptPubKey) 151 | .ToArray(); 152 | builder = new TransactionBuilder(); 153 | var toBob = 154 | builder 155 | .AddCoins(aliceVotingCoin) 156 | .AddKeys(alice) 157 | .SendAsset(bob, new AssetMoney(votingCoin, 1)) 158 | .BuildTransaction(true); 159 | repo.Transactions.Put(toBob); 160 | ``` 161 | 162 | **SetChange**がないことがわかるだろう。それはインプットのカラードコインが完全に使われているからで、お釣りとして戻すものがないからである。 163 | 164 | ### 投票 {#voting} 165 | 166 | サトシがとても忙しすぎて投票しないことに決めたとしよう。またボブは自分の意思決定を表さないといけない。 167 | その投票では会社が銀行に対して、新しい設備投資のために負債借り入れを申し入れるかどうかに関してだ。 168 | 169 | ボスは会社のウェブサイトでこう周知した。 170 | 171 | 賛成なら 1HZwkjkeaoZfTSaJxDw6aKkxp45agDiEzN にコインを、反対なら 1F3sAm6ZtwLAUnj7d38pGFxtP3RVEvtsbV にコインを送ること。 172 | 173 | ボブは会社は負債を借り入れるべきだと決めた。 174 | 175 | ![](../assets/PowerCoin5.png) 176 | 177 | ```cs 178 | var bobVotingCoin = ColoredCoin.Find(toVoters, repo) 179 | .Where(c => c.ScriptPubKey == bob.ScriptPubKey) 180 | .ToArray(); 181 | 182 | builder = new TransactionBuilder(); 183 | var vote = 184 | builder 185 | .AddCoins(bobVotingCoin) 186 | .AddKeys(bob) 187 | .SendAsset(BitcoinAddress.Create("1HZwkjkeaoZfTSaJxDw6aKkxp45agDiEzN"), 188 | new AssetMoney(votingCoin, 1)) 189 | .BuildTransaction(true); 190 | ``` 191 | 192 | さてボスは投票結果を自動計算できる。その結果、賛成が1、反対が0で賛成多数のため、負債を借り入れる。 193 | すべての参加者が自分たちでも結果を数えられる。 194 | 195 | ### 代案:リカーディアン・コントラクトを使う {#alternative-use-of-ricardian-contract} 196 | 197 | これまでのエクササイズでは、ボスがブロックチェーンの外の世界、つまり会社のウェブサイトで投票の方法をアナウンスした。 198 | 199 | これはうまく機能したが、ボブはそのウェブサイトが存在していることを知る必要があった。 200 | 201 | もう1つの解決法はブロックチェーンで、つまり**Asset Definition File**の中で直接、投票の方法を記録してしまうことだ。そうするとソフトウェアが自動的にそれを把握し、ボブにそれを提示させることができる。 202 | 203 | それによって変わるコードはほんの少しで、Voting Coinを投票する人に発行するところだ。 204 | 205 | ```cs 206 | issuance = GetCoins(init2, votingCoin).Select(c => new IssuanceCoin(c)).ToArray(); 207 | issuance[0].DefinitionUrl = new Uri("http://boss.com/vote01.json"); 208 | builder = new TransactionBuilder(); 209 | var toVoters = 210 | builder 211 | .AddCoins(issuance) 212 | .AddKeys(votingCoin) 213 | .IssueAsset(alice, new AssetMoney(votingCoin, 1)) 214 | .IssueAsset(satoshi, new AssetMoney(votingCoin, 1)) 215 | .SetChange(votingCoin) 216 | .BuildTransaction(true); 217 | repo.Transactions.Put(toVoters); 218 | ``` 219 | 220 | このケースでは、ボブがvoting coinを発行する中で**Asset Definition File**が記録されていたことを把握することができる。それはスキーマが部分的に[Open Assetに明示されている](https://github.com/OpenAssets/open-assets-protocol/blob/master/asset-definition-protocol.mediawiki)JSONの他の何物でもない。スキーマは以下のような情報を持つように拡張することができる。 221 | 222 | * 投票の期限 223 | * 各候補に対する投票先 224 | * Asset Definition Fileに記録されている内容の、人間の目に優しい表現 225 | 226 | しかしハッカーが投票権を盗みたいと思っているとしよう。彼はいつもJSONのドキュメントを操作することができる(もしくは中間者が攻撃したり、ボスのウェブサイトに物理的にアクセスしたりまたはボブのソフトウェアに物理的にアクセスしたり)ことで、ボブは騙されて異なる候補に投票してしまう。 227 | 228 | 署名することによって**Asset Definition File**を**リカーディアン・コントラクト**に置き換えることで、ボブのソフトウェアがあらゆる変更をすぐに検知できるようになるだろう(Asset Definition Protocolの[Proof Of Authenticity](https://github.com/OpenAssets/open-assets-protocol/blob/master/asset-definition-protocol.mediawiki)を見てほしい)。 229 | 230 | -------------------------------------------------------------------------------- /other_types_of_asset/proof_of_burn_and_reputation.md: -------------------------------------------------------------------------------- 1 | ## Proof of Burn と評判 {#proof-of-burn-and-reputation} 2 | 3 | ここでの問題は単純だ。P2Pのマーケットでは法的な執行はあまりにもコストが高くつきすぎるが、どのようにして参加者が詐欺にあう可能性を最小化できるだろうか。 4 | 5 | OpenBaazarは決定力のある評価としてproof of burnを使おうとしている[先駆者](https://gist.github.com/dionyziz/e3b296861175e0ebea4b)だ。 6 | 7 | 詐欺対策はいくつかの方法(エスクロー、公証人/仲裁人)があるが、ここで探求するのはProof Of Burnと呼ばれるものだ。 8 | 9 | 自分が、中世で何人かの地元の商人と一緒に小さい村に住んでいることを想像してほしい。 10 | ある日、旅人の商人があなたの村に来て、地元の価格と比べると信じられないくらい安い価格でいくつか商品を売ろうとしている。 11 | 12 | しかしその旅人の商品は、悪質な商品で人を騙す手口に精通していた。なぜならば土着の商人と比べて、評価を失うことは旅人の商品にとっては取るに足らない代償だからだ。 13 | 土着の商人は素晴らしい店、広告とその評価に投資していた。不幸な顧客は簡単にそれを壊すことができる。しかし旅人の商人は土着の店を持っていないし、一時的な評価なんぞ、人を騙さないようにするきっかけにはまったくならない。 14 | 15 | インターネットでは、アイデンティティを作ることはとてもたやすく、すべての商人は中世以降の旅人の商人になりえる。 16 | マーケットの提供者の解決策は、マーケットにおけるすべての参加者の実際のアイデンティティを集め、そして法的執行を可能とすることだ。 17 | 18 | もしAmazonやEbayで詐欺にあったら、銀行が結構な確率であなたにお金を戻してくれることだろう。なぜならばAmazonやEbayに連絡することで泥棒を見つける方法があるからだ。 19 | 20 | 単純なP2Pのマーケットでビットコインを使うとき、泥棒を見つけることはできない。もし詐欺にあうと、お金を失ってしまう。 21 | ということで、どのようにして買い手は旅人の商人を信じることができるだろうか? 22 | その答えは、その人が評価に対してどの程度投資をしているかをチェックすることだ。 23 | 24 | 善良な売り手なら、その自信を顧客に示したいと思うだろう。そのためには富を削るだろうし、すべての顧客はそれを見るだろう。これが「評価に投資する」ことの定義だ。 25 | 26 | あなたが評価のために50BTCを使ったとしよう。そして顧客はあなたから2BTCの商品を買いたいとする。顧客はあなたが自分を騙さないと信じる良い理由がある。なぜならばあなたが、詐欺を働くことによって彼からだまし取ることができるもの以上に、評価に対して投資しているからだ。 27 | あなたが顧客を騙すことは経済的に有益ではないということになる。 28 | 29 | 技術的な詳細はきっと時間がたつにつれてバリエーションが増えたり変わったりするだろうが、ここにはProof of Burnの例を示す。 30 | 31 | ```cs 32 | var alice = new Key(); 33 | 34 | //Giving some money to alice 35 | var init = new Transaction() 36 | { 37 | Outputs = 38 | { 39 | new TxOut(Money.Coins(1.0m), alice), 40 | } 41 | }; 42 | 43 | var coin = init.Outputs.AsCoins().First(); 44 | 45 | //Burning the coin 46 | var burn = new Transaction(); 47 | burn.Inputs.Add(new TxIn(coin.Outpoint) 48 | { 49 | ScriptSig = coin.ScriptPubKey 50 | }); //Spend the previous coin 51 | 52 | var message = "Burnt for \"Alice Bakery\""; 53 | var opReturn = TxNullDataTemplate 54 | .Instance 55 | .GenerateScriptPubKey(Encoding.UTF8.GetBytes(message)); 56 | burn.Outputs.Add(new TxOut(Money.Coins(1.0m), opReturn)); 57 | burn.Sign(alice, false); 58 | 59 | Console.WriteLine(burn); 60 | ``` 61 | 62 | ```json 63 | { 64 | …. 65 | "in": [ 66 | { 67 | "prev_out": { 68 | "hash": "0767b76406dbaa95cc12d8196196a9e476c81dd328a07b30954d8de256aa1e9f", 69 | "n": 0 70 | }, 71 | "scriptSig": "304402202c6897714c69b3f794e730e94dd0110c4b15461e221324b5a78316f97c4dffab0220742c811d62e853dea433e97a4c0ca44e96a0358c9ef950387354fbc24b8964fb01 03fedc2f6458fef30c56cafd71c72a73a9ebfb2125299d8dc6447fdd12ee55a52c" 72 | } 73 | ], 74 | "out": [ 75 | { 76 | "value": "1.00000000", 77 | "scriptPubKey": "OP_RETURN 4275726e7420666f722022416c6963652042616b65727922" 78 | } 79 | ] 80 | } 81 | ``` 82 | 83 | ビットコインブロックチェーンで一度、このトランザクションが作成されるだけで、アリスが自分のベーカリーにお金を投資したという否定できない証明となる。 84 | `ScriptPubKey OP_RETURN 4275726e7420666f722022416c6963652042616b65727922`を伴うコインはいかなる方法でも使えないようになっており、これらのコインは永遠に失われる。 85 | 86 | -------------------------------------------------------------------------------- /other_types_of_asset/ricardian_contracts.md: -------------------------------------------------------------------------------- 1 | ## リカーディアン・コントラクト {#ricardian-contracts} 2 | 3 | 本章は[Coinprismのブログ](http://blog.coinprism.com/2014/12/10/colored-coins-and-ricardian-contracts/)で書いた記事のコピーとなっている。書いた時点ではNBitcoinはリカーディアン・コントラクトに関連するコードはまったくなかった。 4 | 5 | ### リカーディアン・コントラクトとはなにか {#what-is-a-ricardian-contract} 6 | 7 | 一般的にアセットは特定の条件下で発行者に償還される権利を表現するものをいう。 8 | 9 | * 会社の株式によって、配当をもらう権利が与えられる 10 | * 公債によって満期になれば、元本を取り返す権利と毎期に利子を得られる権利を与えられる 11 | * 投票権によって、何らかのエンティティを決定するために投票する権利を与えられる(会社や選挙) 12 | * これらのミックスもありえる:株式によって会社の社長を選ぶ投票券を与えられもするだろう。 13 | 14 | このような権利は典型的に契約の中に列挙され、発行者によって署名される。(必要であれば公証人のように信頼された第三者によっても署名される) 15 | 16 | リカーディアン・コントラクトは暗号によって発行者から署名され、アセットと切り離すことができない契約のことをいう。 17 | 18 | だからそういった契約は否定したり改ざんしたりすることはできない。明白に発行者によって署名されているからだ。 19 | このような契約は発行者と執行者との間で信頼された状態が保てるし、もしくは公表することもできる。 20 | 21 | オープンアセットはすでにコアプロトコルを変えることなく、それらすべてをサポートしている。本章でどのように実装されているかを述べる。 22 | 23 | ### オープンアセット中のリカーディアン・コントラクト {#ricardian-contract-inside-open-asset} 24 | 25 | [このサイト](http://iang.org/papers/ricardian_contract.html)にリカーディアン・コントラクトの公式の定義がある。 26 | 27 | 1. 発行者によって、契約がアセットの所持者に示され、 28 | 2. アセットの所持者が有し、発行者によって執行される様々な権利に対応し、 29 | 3. 簡単に人が読めて(契約書のように) 30 | 4. プログラムによって処理でき(データベースのように解釈ができ) 31 | 5. デジタル署名されていて 32 | 6. 鍵とサーバーの情報を含み、 33 | 7. ユニークで安全な識別子と結び付けられている。 34 | 35 | アセットIDは、以下のような方法でオープンアセットによって特定される。 36 | 37 | `AssetId = Hash160(ScriptPubKey)` 38 | 39 | **ScriptPubKey**をP2SHで作ってみよう。 40 | 41 | `ScriptPubKey = OP_HASH160 Hash(RedeemScript) OP_EQUAL` 42 | 43 | RedeemScriptはこうだ。 44 | 45 | `RedeemScript = HASH160(RicardianContract) OP_DROP IssuerScript` 46 | 47 | **IssureScript**とは1人の発行者に対しては古典的なP2PKHになるが、発行に対して何人かの合意が必要ならばマルチシグ(たとえば発行者と公証人)となる。 48 | 49 | Bitcoin 0.10から、IssureScriptは任意となり、内容はなんでも良いということは注釈しておきたい。 50 | 51 | **リカーディアン・コントラクト**は任意で、秘匿しておける。契約をもっている人なら誰でも、ScriptPubKeyのハッシュのおかげでその契約がこのアセットに適用されることを証明できる。 52 | 53 | しかし、リカーディアン・コントラクトを可視化し、Asset Definition Protocolをもつウォレットクライアントで確認できるようにしてみよう。 54 | 55 | A、BまたはCに対しての選挙権を発行していることにしてみよう。 56 | 57 | オープンアセットのマーカーに、次のアセット定義のURL:`u=http://issuer.com/contract`を追加してみよう。 58 | 59 | [http://issuer.com/contract](http://issuer.com/contract)で、次のような[アセットの定義ファイル](https://github.com/OpenAssets/open-assets-protocol/blob/8b945ba68a781358947325ac008cdd740c89adb3/asset-definition-protocol.mediawiki)を作ってみよう。 60 | 61 | ```json 62 | { 63 | "IssuerScript" : IssuerScript, 64 | "name" : "MyAsset", 65 | "contract_url" : "http://issuer.com/readableContract", 66 | "contract_hash" : "DKDKocezifefiouOIUOIUOIufoiez980980", 67 | "Type" : "Vote", 68 | "Candidates" : ["A","B","C"], 69 | "Validity" : "10 jan 2015" 70 | } 71 | ``` 72 | 73 | これでリカーディアン・コントラクトを定義できる。 74 | 75 | `RicardianContract = AssetDefinitionFile` 76 | 77 | This terminate our RicardianContract implemented in OA. 78 | 79 | ### チェックリスト {#check-list} 80 | 81 | * **発行者によって契約がアセットの所持者に示され、** 82 | 契約が発行者によって主体的に執行され、変更されず、発行者が新しいアセットを発行する都度署名される。 83 | 84 | * **アセットの所持者が有し、発行者によって執行される様々な権利に対応し、** 85 | このサンプルの中での権利は2015年1月10日までに候補者A、BまたはCに投票する権利を与えられる。 86 | 87 | * **簡単に人が読めて(契約書のように)** 88 | contract\_urlで人が読める契約となっている。しかしJSONでもひょっとすると十分かもしれない。 89 | 90 | * **プログラムによって処理でき(データベースのように解釈ができ)** 91 | 投票の詳細はJSONフォーマットの中の**AssetDefinitionFile**のうちにあり、契約の真正性は**IssureScript**と**ScriptPubKey**のハッシュを使ってソフトウェアによって確かめられる。 92 | 93 | * **デジタル署名されていて** 94 | **ScriptPubKey**は、発行者がアセット、つまり契約のハッシュまたはさらに言えば契約自体を発行するときに署名される。 95 | 96 | * **鍵とサーバーの情報を含む。 informationIssureScript**は契約に含まれる。 97 | 98 | * **ユニークで安全な識別子と結び付けられている。** 99 | **アセットID**は、変更できず一意である**ScriptPubKeyのハッシュ**によって定義される。 100 | 101 | ### 何のためのものか? {#what-is-it-for} 102 | 103 | リカーディアン・コントラクトがないと、悪意のあるアセット発行者が、アセットの定義ファイルを変更したり否認したりすることが簡単になってしまう。 104 | 105 | リカーディアン・コントラクトによって否認拒否を強制し、契約を変更できないようにして、アセットの償還を受ける者と発行者との間の裁定を容易にする。 106 | 107 | また、アセットの定義ファイルは変更できないから、悪意のある発行者による、契約の破壊行為を防止しながら、アセットを償還者の手元で保管できるようにもなる。 108 | 109 | -------------------------------------------------------------------------------- /other_types_of_asset/transfer_an_asset.md: -------------------------------------------------------------------------------- 1 | ## 資産の移動 {#transfer-an-asset} 2 | 3 | さあ今、僕が **BlockchainProgrammingコイン** を送ったと想定してみよう。 4 | どのようにして僕にそのコインを送り返せるだろうか。 5 | そのためには **カラードコイン** をビルドする必要がある。 6 | 7 | Issuing an Assetで見たとおり、「nico」のアドレスで受け取った10アセットを使いたいということにしよう。 8 | これが使いたいコインである。 9 | 10 | ```json 11 | { 12 | "transactionId": "fa6db7a2e478f3a8a0d1a77456ca5c9fa593e49fd0cf65c7e349e5a4cbe58842", 13 | "index": 0, 14 | "value": 600, 15 | "scriptPubKey": "76a914356facdac5f5bcae995d13e667bb5864fd1e7d5988ac", 16 | "redeemScript": null, 17 | "assetId": "AVAVfLSb1KZf9tJzrUVpktjxKUXGxUTD4e", 18 | "quantity": 10 19 | } 20 | ``` 21 | 22 | そしてこれが、コードで上記のようなカラードコインを初期化する方法である。 23 | 24 | ```cs 25 | var coin = new Coin( 26 | fromTxHash: new uint256("fa6db7a2e478f3a8a0d1a77456ca5c9fa593e49fd0cf65c7e349e5a4cbe58842"), 27 | fromOutputIndex: 0, 28 | amount: Money.Satoshis(2000000), 29 | scriptPubKey: new Script(Encoders.Hex.DecodeData("76a914356facdac5f5bcae995d13e667bb5864fd1e7d5988ac"))); 30 | BitcoinAssetId assetId = new BitcoinAssetId("AVAVfLSb1KZf9tJzrUVpktjxKUXGxUTD4e"); 31 | ColoredCoin colored = coin.ToColoredCoin(assetId, 10); 32 | ``` 33 | 34 | より簡単にカラードコインを得るために、ウェブサービスやカスタマイズされたコードをどのように使えるかをあとで説明するつもりだ。 35 | また、手数料を支払うためにさらにコイン(forFees)を必要とする。 36 | アセットの移動は **TransactionBuilder** を使えば本当に簡単である。 37 | 38 | ```cs 39 | var book = BitcoinAddress.Create("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB"); 40 | var nicoSecret = new BitcoinSecret("??????????"); 41 | var nico = nicoSecret.GetAddress(); //15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe 42 | 43 | var forFees = new Coin( 44 | fromTxHash: new uint256("7f296e96ec3525511b836ace0377a9fbb723a47bdfb07c6bc3a6f2a0c23eba26"), 45 | fromOutputIndex: 0, 46 | amount: Money.Satoshis(4425000), 47 | scriptPubKey: new Script(Encoders.Hex.DecodeData("76a914356facdac5f5bcae995d13e667bb5864fd1e7d5988ac"))); 48 | 49 | TransactionBuilder builder = new TransactionBuilder(); 50 | var tx = builder 51 | .AddKeys(nicoSecret) 52 | .AddCoins(colored, forFees) 53 | .SendAsset(book, new AssetMoney(assetId, 10)) 54 | .SetChange(nico) 55 | .SendFees(Money.Coins(0.0001m)) 56 | .BuildTransaction(true); 57 | Console.WriteLine(tx); 58 | ``` 59 | 60 | ```json 61 | { 62 | …. 63 | "out": [ 64 | { 65 | "value": "0.00000000", 66 | "scriptPubKey": "OP_RETURN 4f410100010a00" 67 | }, 68 | { 69 | "value": "0.00000600", 70 | "scriptPubKey": "OP_DUP OP_HASH160 c81e8e7b7ffca043b088a992795b15887c961592 OP_EQUALVERIFY OP_CHECKSIG" 71 | }, 72 | { 73 | "value": "0.04415000", 74 | "scriptPubKey": "OP_DUP OP_HASH160 356facdac5f5bcae995d13e667bb5864fd1e7d59 OP_EQUALVERIFY OP_CHECKSIG" 75 | } 76 | ] 77 | } 78 | ``` 79 | 80 | Confirmedされていないとはいえ、基本的にはアセットの移動はこれで成功だ。 81 | 82 | ![](../assets/Coinprism2.png) 83 | -------------------------------------------------------------------------------- /other_types_of_asset/unit_tests.md: -------------------------------------------------------------------------------- 1 | ## 単体テスト {#unit-tests} 2 | 3 | 前の章では、**カラードコイン** 資産をコードするのに苦労していたように見えたかもしれない。 4 | なぜかというと **カラードコイン** から **トランザクション** を生成する方法を見せたかっただけだからだ。 5 | 6 | 現場では、カラードコインのトランザクションや資金を取得するためには、サードパーティーのAPIに頼ろうとするだろう。しかしそれは良いアイディアではひょっとするとないかもしれない。なぜならば、APIの提供者に対しての信頼に基づく、プログラムの依存関係ができてしまうからだ。 7 | 8 | **NBitcoin** によって、ウェブサービスに頼っても良いし、カラードコインの **トランザクション** をプログラム自身に取得させても良くなる。これによって、コードの単体テストに柔軟性を持つことができるようになった。 9 | 10 | 2つの発行者を紹介しよう:シルバーとゴールドだ。そして3人の参加者を紹介しよう:ボブ、アリスとサトシだ。 11 | シルバー、ゴールドとサトシにビットコインを送る模擬のトランザクションを作ってみよう。 12 | 13 | ```cs 14 | var gold = new Key(); 15 | var silver = new Key(); 16 | var goldId = gold.PubKey.ScriptPubKey.Hash.ToAssetId(); 17 | var silverId = silver.PubKey.ScriptPubKey.Hash.ToAssetId(); 18 | 19 | var bob = new Key(); 20 | var alice = new Key(); 21 | var satoshi = new Key(); 22 | 23 | var init = new Transaction() 24 | { 25 | Outputs = 26 | { 27 | new TxOut("1.0", gold), 28 | new TxOut("1.0", silver), 29 | new TxOut("1.0", satoshi) 30 | } 31 | }; 32 | ``` 33 | 34 | **Init** はカラードコインの発行も移動も全く含んでいない。しかし、それを確信したいと思っている場面を想像してみよう。どのように進めればよいだろうか。 35 | 36 | **NBitcoin** では、カラードコインの移動や発行の概要が **ColoredTransaction** と呼ばれるクラスに表現されている。 37 | 38 | ![](../assets/ColoredTransaction.png) 39 | 40 | **ColoredTransaction** クラスによって以下がわかる。 41 | 42 | * どの **トランザクションインプット** がどのアセットを使うのか 43 | * どの **トランザクションアウトプット** がどのアセットを表すのか 44 | * どの **トランザクションアウトプット** がどのアセットを移動するのか 45 | 46 | しかし今私たちにとって興味をわかせるメソッドは **FetchColors** で、これによってトランザクションインプットに与えたトランザクションから、カラードコインの情報を抜き出すことができる。 47 | 48 | FetchColorsが **IColoredTransactionRepository** に依存していることを見てみよう。 49 | 50 | ![](../assets/IColoredCoinTransactionRepository.png) 51 | 52 | **IColoredTransactionRepository** はトランザクションIDから、**カラードコインのトランザクション** を示してくれるストアでしかない。しかしこれは **ITransactionRepository** に依存関係があることがわかるだろう。ITransactionRepositoryはトランザクションIDとそのトランザクションをマッピングしてくれるものだ。 53 | 54 | **IColoredTransactionRepository** の実行は、カラードコインの操作を担う公開されたAPIである **CoinprismColoredTransactionRepository** の実行と同義だ。 55 | しかし、簡単に自分自身でそれらを行うことができる。それがここで示すように、**FetchColors** がどのように動くかでわかる。 56 | 57 | 最も単純なケースを見てみよう。**IColoredTransactionRepository** がカラードコインを知っているから、そのケースであれば **FetchColors** はその結果を取ってくるだけだ。 58 | 59 | ![](../assets/FetchColors.png) 60 | 61 | 2番目のケースでは、**IColoredTransactionRepository** がカラードコインのトランザクションについて何も知らない場合だ。 62 | そのときはオープンアセットの仕様に基づいて **FetchColors** を使って、カラードコインを算出する必要がある。 63 | 64 | しかし、カラードコインを求めるためには、**FetchColors** はカラードコインの親トランザクションを必要とする。 65 | だから **ITransactionRepository** 上で各トランザクションを取得し、それらに対して **FetchColors** をコールするのだ。 66 | 一度 **FetchColors** が再帰的に親トランザクションのカラードコインを解明すると、カラードコインのトランザクションを算出して、**IColoredTransactionRepository** にその結果を再度引き渡し、結果を得る。 67 | 68 | ![](../assets/FetchColors2.png) 69 | 70 | これによって、将来的に発生する、トランザクションのカラードコインを取得するリクエストが素早く解決される。 71 | **IColoredTransactionRepository** は読み取り専用だ(**CoinprismColoredTransactionRepository** と同じでPutする操作が無視される)。 72 | 73 | さあ、例に戻ろう。 74 | ユニットテストを書くときのトリックは、メモリ上の **IColoredTransactionRepository** を使うことだ。 75 | 76 | ```cs 77 | var repo = new NoSqlColoredTransactionRepository(); 78 | ``` 79 | 80 | さあ、**init** トランザクションを格納しよう。 81 | 82 | ```cs 83 | repo.Transactions.Put(init); 84 | ``` 85 | 86 | 注釈するが、Putは拡張メソッドなので、以下の参照を追加する必要がある。 87 | 88 | ```cs 89 | using NBitcoin.OpenAsset; 90 | ``` 91 | 92 | ファイルの1番上に、参照を付け足して欲しい。 93 | 94 | そしたら、カラードコインを抽出できる。 95 | 96 | ```cs 97 | ColoredTransaction color = ColoredTransaction.FetchColors(init, repo); 98 | Console.WriteLine(color); 99 | ``` 100 | 101 | ```json 102 | { 103 | "inputs": [], 104 | "issuances": [], 105 | "transfers": [], 106 | "destructions": [] 107 | } 108 | ``` 109 | 110 | 想定どおり、**init** トランザクションはカラードコインのインプットも発行も移動も破壊も何も持っていない。 111 | 112 | ということで、SilverとGoldに送られたコインを、発行用のコインとして使ってみよう。 113 | 114 | ```cs 115 | var issuanceCoins = 116 | init 117 | .Outputs 118 | .AsCoins() 119 | .Take(2) 120 | .Select((c, i) => new IssuanceCoin(c)) 121 | .OfType() 122 | .ToArray(); 123 | ``` 124 | 125 | Goldが最初、次にSilverとなっている。 126 | 127 | 前の章でやったとおり、**TransactionBuilder** を使ってGoldをSatoshiに送り、リポジトリに結果として生成されるトランザクションを格納し、結果を表示できる。 128 | 129 | ```cs 130 | { 131 | "inputs": [], 132 | "issuances": [ 133 | { 134 | "index": 0, 135 | "asset": "ATEwaRSNeCgBjxjcur7JtfypFjqQgAtLJs", 136 | "quantity": 10 137 | } 138 | ], 139 | "transfers": [], 140 | "destructions": [] 141 | } 142 | ``` 143 | 144 | これは最初の **トランザクションアウトプット** には10goldあるということだ。 145 | 146 | さて今、**サトシ** が **アリス** に4goldを送りたいということにしてみよう。 147 | 最初にサトシはトランザクションから **カラードコイン** を取得する。 148 | 149 | ```cs 150 | var goldCoin = ColoredCoin.Find(sendGoldToSatoshi, color).FirstOrDefault(); 151 | ``` 152 | 153 | そしてこのようにトランザクションを生成する。 154 | 155 | ```cs 156 | builder = new TransactionBuilder(); 157 | var sendToBobAndAlice = 158 | builder 159 | .AddKeys(satoshi) 160 | .AddCoins(goldCoin) 161 | .SendAsset(alice, new AssetMoney(goldId, 4)) 162 | .SetChange(satoshi) 163 | .BuildTransaction(true); 164 | ``` 165 | 166 | **NotEnoughFundsException** が発生してしまうだろう。 167 | なぜかというと、このトランザクションはトランザクションインプット(**goldコイン**)に600satoshiあって、トランザクションアウトプットに1200satoshiある。(1つ目の **トランザクションアウトプット** はアリスにアセットを送るもので、もう1つはサトシにお釣りを送るものだ) 168 | 169 | つまり600satoshi不足しているのだ。 170 | サトシに送られている **init** トランザクションにある最後の1BTCに相当する **コイン** をトランザクションに加えることで解決できる。 171 | 172 | ```cs 173 | var satoshiBtc = init.Outputs.AsCoins().Last(); 174 | builder = new TransactionBuilder(); 175 | var sendToAlice = 176 | builder 177 | .AddKeys(satoshi) 178 | .AddCoins(goldCoin, satoshiBtc) 179 | .SendAsset(alice, new AssetMoney(goldId, 4)) 180 | .SetChange(satoshi) 181 | .BuildTransaction(true); 182 | repo.Transactions.Put(sendToAlice); 183 | color = ColoredTransaction.FetchColors(sendToAlice, repo); 184 | ``` 185 | 186 | トランザクションとカラードコインの内容を見てみよう。 187 | 188 | ```cs 189 | Console.WriteLine(sendToAlice); 190 | Console.WriteLine(color); 191 | ``` 192 | 193 | ```json 194 | { 195 | …. 196 | "in": [ 197 | { 198 | "prev_out": { 199 | "hash": "46117f3ef44f2dfd87e0bc3f461f48fe9e2a3a2281c9b3802e339c5895fc325e", 200 | "n": 0 201 | }, 202 | "scriptSig": "304502210083424305549d4bb1632e2c67736383558f3e1d7fb30ce7b5a3d7b87a53cdb3940220687ea53db678b467b98a83679dec43d27e89234ce802daf14ed059e7a09557e801 03e232cda91e719075a95ede4c36ea1419efbc145afd8896f36310b76b8020d4b1" 203 | }, 204 | { 205 | "prev_out": { 206 | "hash": "aefa62270999baa0d57ddc7d2e1524dd3828e81a679adda810657581d7d6d0f6", 207 | "n": 2 208 | }, 209 | "scriptSig": "30440220364a30eb4c8a82cc2a79c54d0518b8ba0cf4e49c73a5bbd17fe1a5683a0dfa640220285e98f3d336f1fa26fb318be545162d6a36ce1103c8f6c547320037cb1fb8e901 03e232cda91e719075a95ede4c36ea1419efbc145afd8896f36310b76b8020d4b1" 210 | } 211 | ], 212 | "out": [ 213 | { 214 | "value": "0.00000000", 215 | "scriptPubKey": "OP_RETURN 4f41010002060400" 216 | }, 217 | { 218 | "value": "0.00000600", 219 | "scriptPubKey": "OP_DUP OP_HASH160 5bb41cd29f4e838b4b0fdcd0b95447dcf32c489d OP_EQUALVERIFY OP_CHECKSIG" 220 | }, 221 | { 222 | "value": "0.00000600", 223 | "scriptPubKey": "OP_DUP OP_HASH160 469c5243cb08c82e78a8020360a07ddb193f2aa8 OP_EQUALVERIFY OP_CHECKSIG" 224 | }, 225 | { 226 | "value": "0.99999400", 227 | "scriptPubKey": "OP_DUP OP_HASH160 5bb41cd29f4e838b4b0fdcd0b95447dcf32c489d OP_EQUALVERIFY OP_CHECKSIG" 228 | } 229 | ] 230 | } 231 | Colored : 232 | { 233 | "inputs": [ 234 | { 235 | "index": 0, 236 | "asset": " ATEwaRSNeCgBjxjcur7JtfypFjqQgAtLJs ", 237 | "quantity": 10 238 | } 239 | ], 240 | "issuances": [], 241 | "transfers": [ 242 | { 243 | "index": 1, 244 | "asset": " ATEwaRSNeCgBjxjcur7JtfypFjqQgAtLJs ", 245 | "quantity": 6 246 | }, 247 | { 248 | "index": 2, 249 | "asset": " ATEwaRSNeCgBjxjcur7JtfypFjqQgAtLJs ", 250 | "quantity": 4 251 | } 252 | ], 253 | "destructions": [] 254 | } 255 | ``` 256 | 257 | ついに外部的な依存なしで、アセットを発行し移動する単体テストを実行できたわけだ。 258 | 259 | もしサードパーティーのサービスに依存したくなければ、**IColoredTransactionRepository** を自前で作ることもできる。 260 | 261 | より詳しい内容は[NBitcoin tests](https://github.com/MetacoSA/NBitcoin/blob/master/NBitcoin.Tests/transaction_tests.cs)で見ることができるし、コードプロジェクトの中にある私の記事の1つの「[Build Them all](https://www.codeproject.com/articles/835098/nbitcoin-build-them-all)」でも見ることができる。(マルチシグでのカラードコインの発行や交換) 262 | -------------------------------------------------------------------------------- /other_types_of_ownership/README.md: -------------------------------------------------------------------------------- 1 | # その他の所有権 {#other-types-of-ownership} 2 | 3 | ビットコインブロックチェーン上で比較的よく見るタイプの **ScriptPubKey** について手短に話をしよう。それから、「TransactionBuilderを使ってみる」の章の最後で、それぞれのタイプに関して簡単に署名する方法を説明しよう。 4 | -------------------------------------------------------------------------------- /other_types_of_ownership/arbitrary.md: -------------------------------------------------------------------------------- 1 | ## 任意性 {#arbitrary} 2 | 3 | ビットコインコアのバージョン0.10から、**RedeemScript** の内容は任意とすることができるようになった。それはビットコインのスクリプト言語を用いて、「所有権」が何を意味するかに関して自分の定義を作ることができるようになったということだ。 4 | 5 | たとえば僕が、UTF8にバイト化された僕の誕生日を知っている人、もしくは **1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB** に対応する秘密鍵を知っている人になら、誰でもビットコインをあげられるとしよう。 6 | 7 | スクリプト言語の詳細についてはスコープ外だが、いろいろなウェブサイト上で簡単にドキュメントを見つけられるし、スタックベースの言語なのでアセンブラを触っていた人ならだれでも読むことができるはずだ。 8 | 9 | > **注釈**:\([nopara73](https://github.com/nopara73)\)僕は [Davide De Rosa's tutorial](http://davidederosa.com/basic-blockchain-programming/bitcoin-script-language-part-one/) が1番楽しいチュートリアルだと思う。 10 | 11 | さあ最初は **RedeemScript** を作ってみよう。 12 | 13 | > **注釈**:このコードが正しく動くようにするために、**プロジェクト** -> **参照の編集** -> **System.Numerics** の順番にクリックして参照を設定しよう。 14 | 15 | ```cs 16 | BitcoinAddress address = BitcoinAddress.Create("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB"); 17 | var birth = Encoding.UTF8.GetBytes("18/07/1988"); 18 | var birthHash = Hashes.Hash256(birth); 19 | Script redeemScript = new Script( 20 | "OP_IF " 21 | + "OP_HASH256 " + Op.GetPushOp(birthHash.ToBytes()) + " OP_EQUAL " + 22 | "OP_ELSE " 23 | + address.ScriptPubKey + " " + 24 | "OP_ENDIF"); 25 | ``` 26 | 27 | この **RedeemScipt** は、**ScriptCoin** を使う2つの方法を示している。2つの方法とは、1つが **birthHash**(僕の誕生日)を導出してくれるデータを知っていることで、もう1つがそのビットコインアドレスを持っていることだ。 28 | 29 | たとえば、この **redeemScript** にビットコインを送ったとしよう。 30 | 31 | ```cs 32 | var tx = new Transaction(); 33 | tx.Outputs.Add(new TxOut(Money.Parse("0.0001"), redeemScript.Hash)); 34 | ScriptCoin scriptCoin = tx.Outputs.AsCoins().First().ToScriptCoin(redeemScript); 35 | ``` 36 | 37 | そのアウトプットを使うトランザクションを作ってみよう。 38 | 39 | ```cs 40 | //Create spending transaction 41 | Transaction spending = new Transaction(); 42 | spending.AddInput(new TxIn(new OutPoint(tx, 0))); 43 | ``` 44 | 45 | 最初の選択肢は僕の誕生日を知っていて、**scriptSig** の中でそれを証明することだ。 46 | 47 | ```cs 48 | ////Option 1 : Spender knows my birthdate 49 | Op pushBirthdate = Op.GetPushOp(birth); 50 | Op selectIf = OpcodeType.OP_1; //go to if 51 | Op redeemBytes = Op.GetPushOp(redeemScript.ToBytes()); 52 | Script scriptSig = new Script(pushBirthdate, selectIf, redeemBytes); 53 | spending.Inputs[0].ScriptSig = scriptSig; 54 | ``` 55 | 56 | **scriptSig** の中で、**OP\_1** を入れたから、条件判定の結果、**RedeemScript** の **OP\_IF** の節に入ることがわかる。 57 | このような **scriptSig** を生成するテンプレートはないが、手動でP2SHの **scriptSig** を作る方法がわかるだろう。 58 | 59 | そして **scriptSig** が **scriptPubKey** の所有権を証明することを確認できる。 60 | 61 | ```cs 62 | //Verify the script pass 63 | var result = spending 64 | .Inputs 65 | .AsIndexedInputs() 66 | .First() 67 | .VerifyScript(tx.Outputs[0].ScriptPubKey); 68 | Console.WriteLine(result); // True 69 | ``` 70 | 71 | このビットコインを使用する2番目の方法は、**1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB** が自分のビットコインアドレスであることを証明することだ。 72 | 73 | ``` 74 | ////Option 2 : Spender knows my private key 75 | BitcoinSecret secret = new BitcoinSecret("..."); 76 | var sig = spending.SignInput(secret, scriptCoin); 77 | var p2pkhProof = PayToPubkeyHashTemplate 78 | .Instance 79 | .GenerateScriptSig(sig, secret.PrivateKey.PubKey); 80 | selectIf = OpcodeType.OP_0; //go to else 81 | scriptSig = p2pkhProof + selectIf + redeemBytes; 82 | spending.Inputs[0].ScriptSig = scriptSig; 83 | ``` 84 | 85 | 以下でビットコインアドレスが自分のものであることの証明の結果を確認できる。 86 | 87 | ```cs 88 | //Verify the script pass 89 | result = spending 90 | .Inputs 91 | .AsIndexedInputs() 92 | .First() 93 | .VerifyScript(tx.Outputs[0].ScriptPubKey); 94 | Console.WriteLine(result); // True 95 | /////////// 96 | ``` 97 | -------------------------------------------------------------------------------- /other_types_of_ownership/multi_sig.md: -------------------------------------------------------------------------------- 1 | ## マルチシグ {#multi-sig} 2 | 3 | ビットコインに対して所有権を共有することができる。 4 | そのためには **m-of-n multi sig** を表す`scriptPubKey`を作る。つまり、ビットコインを使うためには与えられた **n** 個の異なる公開鍵に対して、**m** 個の秘密鍵で署名する必要があるということだ。 5 | 6 | ビットコインを使うためにはボブ、アリスそしてサトシのうち2人が署名する必要のある、マルチシグを作ってみよう。 7 | 8 | ```cs 9 | Key bob = new Key(); 10 | Key alice = new Key(); 11 | Key satoshi = new Key(); 12 | 13 | var scriptPubKey = PayToMultiSigTemplate 14 | .Instance 15 | .GenerateScriptPubKey(2, new[] { bob.PubKey, alice.PubKey, satoshi.PubKey }); 16 | 17 | Console.WriteLine(scriptPubKey); 18 | ``` 19 | 20 | ``` 21 | 2 0282213c7172e9dff8a852b436a957c1f55aa1a947f2571585870bfb12c0c15d61 036e9f73ca6929dec6926d8e319506cc4370914cd13d300e83fd9c3dfca3970efb 0324b9185ec3db2f209b620657ce0e9a792472d89911e0ac3fc1e5b5fc2ca7683d 3 OP_CHECKMULTISIG 22 | ``` 23 | 24 | 見てのとおり、`scriptPubkey`が次のような形式となっている: 25 | 26 | ` OP_CHECKMULTISIG` 27 | 28 | 署名のプロセスは`Transaction.Sign`と呼ばれるものと比べて少し複雑になっていて、それではマルチシグでは署名できない。 29 | 30 | そのテーマについてはあとでより詳しく話すとして、マルチシグのトランザクションへの署名には`TransactionBuilder`を使うことにしよう。 31 | 32 | マルチシグの`scriptPubKey`が`received`というトランザクションでビットコインを受け取ったとしよう。 33 | 34 | ```cs 35 | var received = new Transaction(); 36 | received.Outputs.Add(new TxOut(Money.Coins(1.0m), scriptPubKey)); 37 | ``` 38 | 39 | ボブとアリスはニコに、彼のサービスへの対価として1.0BTCを支払うことに同意した。ということでまず、彼らはトランザクションから、すでに受け取った`Coin`を取得する。 40 | 41 | ```cs 42 | Coin coin = received.Outputs.AsCoins().First(); 43 | ``` 44 | 45 | ![](../assets/coin.png) 46 | 47 | それから`TransactionBuilder`を使って **まだ署名されていないトランザクション** を生成する。 48 | 49 | ```cs 50 | BitcoinAddress nico = new Key().PubKey.GetAddress(Network.Main); 51 | TransactionBuilder builder = new TransactionBuilder(); 52 | Transaction unsigned = 53 | builder 54 | .AddCoins(coin) 55 | .Send(nico, Money.Coins(1.0m)) 56 | .BuildTransaction(sign: false); 57 | ``` 58 | 59 | そのトランザクションはまだ署名されていない。ここでどのようにアリスが署名するかを示す。 60 | 61 | ```cs 62 | Transaction aliceSigned = 63 | builder 64 | .AddCoins(coin) 65 | .AddKeys(alice) 66 | .SignTransaction(unsigned); 67 | ``` 68 | 69 | ![](../assets/aliceSigned.png) 70 | 71 | それからボブの署名は以下のとおり。 72 | 73 | ```cs 74 | Transaction bobSigned = 75 | builder 76 | .AddCoins(coin) 77 | .AddKeys(bob) 78 | .SignTransaction(aliceSigned); 79 | ``` 80 | 81 | ![](../assets/bobSigned.png) 82 | 83 | そして、ボブとアリスは1つのトランザクションに彼らの署名を結合する。 84 | 85 | ```cs 86 | Transaction fullySigned = 87 | builder 88 | .AddCoins(coin) 89 | .CombineSignatures(aliceSigned, bobSigned); 90 | ``` 91 | 92 | ![](../assets/fullySigned.png) 93 | 94 | ```cs 95 | Console.WriteLine(fullySigned); 96 | ``` 97 | 98 | ```json 99 | { 100 | ... 101 | "in": [ 102 | { 103 | "prev_out": { 104 | "hash": "9df1e011984305b78210229a86b6ade9546dc69c4d25a6bee472ee7d62ea3c16", 105 | "n": 0 106 | }, 107 | "scriptSig": "0 3045022100a14d47c762fe7c04b4382f736c5de0b038b8de92649987bc59bca83ea307b1a202203e38dcc9b0b7f0556a5138fd316cd28639243f05f5ca1afc254b883482ddb91f01 3044022044c9f6818078887587cac126c3c2047b6e5425758e67df64e8d682dfbe373a2902204ae7fda6ada9b7a11c4e362a0389b1bf90abc1f3488fe21041a4f7f14f1d856201" 108 | } 109 | ], 110 | "out": [ 111 | { 112 | "value": "1.00000000", 113 | "scriptPubKey": "OP_DUP OP_HASH160 d4a0f6c5b4bcbf2f5830eabed3daa7304fb794d6 OP_EQUALVERIFY OP_CHECKSIG" 114 | } 115 | ] 116 | } 117 | ``` 118 | 119 | こうしてトランザクションはネットワークに送信できる準備ができた。 120 | 121 | ビットコインネットワークが、ここに説明したとおりマルチシグをサポートしているとしても、1つ質問するに値することがある。「マルチシグの`ScriptPubKey`が、以前の章で見てきたようなビットコインアドレスを使う程度の簡単さで表されていないが、ビットコインに対して知見を持ち合わせていない人に対して、どのようにサトシ、アリスまたはボブのマルチシグに対して支払うようお願いできるのだろうか?」 122 | 123 | `scriptPubKey`をビットコインアドレスと同じくらい簡単に、そしてコンパクトに表現できるとしたら、素晴らしいことだと思わないだろうか? 124 | 125 | そう。これは可能で、**Bitcoin Script Address**、またの名をPay to Script Hash\(P2SH\)と呼ばれている。 126 | 127 | 最近では、ここで見た **Pay To Multi Sigそのもの** や **P2PKそのもの** は、説明したとおりに直接使われることは決してなく、**Pay To Script Hash** による支払いにラップされている。 128 | -------------------------------------------------------------------------------- /other_types_of_ownership/p2pk[h]_pay_to_public_key_[hash].md: -------------------------------------------------------------------------------- 1 | ## P2PK\[H\] \(Pay to Public Key \[Hash\]\) {#p2pk-h-pay-to-public-key-hash} 2 | 3 | ### P2PKH - 要点の振り返り 4 | 5 | **ビットコインアドレス** は **公開鍵のハッシュ** であることを学んだ。 6 | 7 | ```cs 8 | var publicKeyHash = new Key().PubKey.Hash; 9 | var bitcoinAddress = publicKeyHash.GetAddress(Network.Main); 10 | Console.WriteLine(publicKeyHash); // 41e0d7ab8af1ba5452b824116a31357dc931cf28 11 | Console.WriteLine(bitcoinAddress); // 171LGoEKyVzgQstGwnTHVh3TFTgo5PsqiY 12 | ``` 13 | 14 | また、ブロックチェーン上には、**ビットコインアドレス** というようなものはないということも学んだ。ブロックチェーンでは **ScriptPubKey** を用いて受け取り手を認識し、**ScriptPubKey** は、ビットコインアドレスから生成できる。 15 | 16 | ```cs 17 | var scriptPubKey = bitcoinAddress.ScriptPubKey; 18 | Console.WriteLine(scriptPubKey); // OP_DUP OP_HASH160 41e0d7ab8af1ba5452b824116a31357dc931cf28 OP_EQUALVERIFY OP_CHECKSIG 19 | ``` 20 | 21 | 逆も然りであり、ScriptPubKeyからアドレスを取得できる。 22 | 23 | ```cs 24 | var sameBitcoinAddress = scriptPubKey.GetDestinationAddress(Network.Main); 25 | ``` 26 | 27 | ### P2PK\(Pay to Public Key\) 28 | 29 | しかし必ずしも全ての **ScriptPubKey** がビットコインアドレスを表しているというわけではない。たとえばジェネシスと呼ばれているビットコインブロックチェーンの最初のトランザクションがそうだ。 30 | 31 | ```cs 32 | Block genesisBlock = Network.Main.GetGenesis(); 33 | Transaction firstTransactionEver = genesisBlock.Transactions.First(); 34 | var firstOutputEver = firstTransactionEver.Outputs.First(); 35 | var firstScriptPubKeyEver = firstOutputEver.ScriptPubKey; 36 | var firstBitcoinAddressEver = firstScriptPubKeyEver.GetDestinationAddress(Network.Main); 37 | Console.WriteLine(firstBitcoinAddressEver == null); // 正。アドレスが空である。 38 | ``` 39 | 40 | ```cs 41 | Console.WriteLine(firstTransactionEver); 42 | ``` 43 | 44 | ```json 45 | { 46 | … 47 | "out": [ 48 | { 49 | "value": "50.00000000", 50 | "scriptPubKey": "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG" 51 | } 52 | ] 53 | } 54 | ``` 55 | 56 | **scriptPubKey** の形式が違うことがわかる。 57 | 58 | ```cs 59 | Console.WriteLine(firstScriptPubKeyEver); // 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG 60 | ``` 61 | 62 | ビットコインアドレスは次のように表す: 63 | **OP\_DUP OP\_HASH160 <公開鍵ハッシュ> OP\_EQUALVERIFY OP\_CHECKSIG** 64 | 65 | しかし今表示されているものはこうだ:**<公開鍵> OP\_CHECKSIG** 66 | 67 | 実際のところ、初期には、**公開鍵** が直接 **ScriptPubKey** に使われていた。 68 | 69 | ```cs 70 | var firstPubKeyEver = firstScriptPubKeyEver.GetDestinationPublicKeys().First(); 71 | Console.WriteLine(firstPubKeyEver); // 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f 72 | ``` 73 | 74 | 今は主に公開鍵のハッシュを使っている。 75 | 76 | ![](../assets/PPKH.png) 77 | 78 | ```cs 79 | key = new Key(); 80 | Console.WriteLine("Pay to public key : " + key.PubKey.ScriptPubKey); 81 | Console.WriteLine(); 82 | Console.WriteLine("Pay to public key hash : " + key.PubKey.Hash.ScriptPubKey); 83 | ``` 84 | 85 | ``` 86 | Pay to public key : 02fb8021bc7dedcc2f89a67e75cee81fedb8e41d6bfa6769362132544dfdf072d4 OP_CHECKSIG 87 | Pay to public key hash : OP_DUP OP_HASH160 0ae54d4cec828b722d8727cb70f4a6b0a88207b2 OP_EQUALVERIFY OP_CHECKSIG 88 | ``` 89 | 90 | これら2つの支払い方法は **P2PK** \(pay to public key\)や **P2PKH** \(pay to public key hash\)と言われている。 91 | 92 | サトシは後に、以下の2つの理由でP2PKではなくP2PKHを使うことを決めた。 93 | 94 | * 楕円曲線暗号(**公開鍵**や**秘密鍵** に使われれている暗号)が、楕円曲線上の離散対数問題を解くために改良されたショアのアルゴリズムによって解かれてしまうから。簡単に言うとそれが意味するのは、理論上、量子コンピューターがそう遠くない未来に **公開鍵から秘密鍵を導出できてしまう** ということだ。ビットコインを使うときだけ公開鍵を公開することによって、そういった攻撃を無力化することができる(一度使われたビットコインアドレスを二度と使わない前提だが)。 95 | * ハッシュサイズがより小さくなるので(20バイトになる)、印刷するにも小さくできるしQRコードのような小さい記録媒体に埋め込むことがより簡単になる。 96 | 97 | 最近ではP2PKを直接使う理由がないが、後に述べるP2SHと組み合わせてまだ使われている。 98 | 99 | > ([議論](https://www.reddit.com/r/Bitcoin/comments/4isxjr/petition_to_protect_satoshis_coins/d30we6f/)) 初期に使われてしまっているP2PKトランザクションの問題をこのまま放置しておくと、ビットコインの価値に深刻な影響を及ぼすようになるだろう。 100 | 101 | ### Exercise 102 | 103 | \([nopara73](https://github.com/nopara73)\) この章を読んでいる間、略語(P2PK、P2PKH、P2Wなど)がとてもややこしいことに気づいた。 104 | 僕はそこで、レッスンを進める中でその略語に遭遇する都度、何回もその言葉を発音することにした。そうすると突然すべてがわかるようになった。あなたにも同じことをするのをおすすめする。 105 | -------------------------------------------------------------------------------- /other_types_of_ownership/p2sh_pay_to_script_hash.md: -------------------------------------------------------------------------------- 1 | ## P2SH \(Pay To Script Hash\) {#p2sh-pay-to-script-hash} 2 | 3 | 前の章で見たとおり、マルチシグは簡単にコードを書いて動かせはするが、P2SHを使わないと、顧客に対してマルチシグの`scriptPubKey`へビットコインを支払うようにお願いする方法がなかった。`BitcoinAddress`を手渡しできる限りは簡単にできるが。 4 | 5 | **P2SH** または **Pay To Script Hash** は`scriptPubKey`を、それがどれだけ複雑だとしても、簡単な`BitcoinScriptAddress`に表現する方法である。 6 | 7 | 前の章ではこのマルチシグをこのように作っていた。 8 | 9 | ```cs 10 | Key bob = new Key(); 11 | Key alice = new Key(); 12 | Key satoshi = new Key(); 13 | 14 | var scriptPubKey = PayToMultiSigTemplate 15 | .Instance 16 | .GenerateScriptPubKey(2, new[] { bob.PubKey, alice.PubKey, satoshi.PubKey }); 17 | 18 | Console.WriteLine(scriptPubKey); 19 | ``` 20 | 21 | ``` 22 | 2 0282213c7172e9dff8a852b436a957c1f55aa1a947f2571585870bfb12c0c15d61 036e9f73ca6929dec6926d8e319506cc4370914cd13d300e83fd9c3dfca3970efb 0324b9185ec3db2f209b620657ce0e9a792472d89911e0ac3fc1e5b5fc2ca7683d 3 OP_CHECKMULTISIG 23 | ``` 24 | 25 | 複雑だと思わないだろうか? 26 | 27 | その代わりにその`scriptPubKey`が **P2SH** への支払いだとどのように見えるかを見てみよう。 28 | 29 | ```cs 30 | Key bob = new Key(); 31 | Key alice = new Key(); 32 | Key satoshi = new Key(); 33 | 34 | var paymentScript = PayToMultiSigTemplate 35 | .Instance 36 | .GenerateScriptPubKey(2, new[] { bob.PubKey, alice.PubKey, satoshi.PubKey }).PaymentScript; 37 | 38 | Console.WriteLine(paymentScript); 39 | ``` 40 | 41 | ``` 42 | OP_HASH160 57b4162e00341af0ffc5d5fab468d738b3234190 OP_EQUAL 43 | ``` 44 | 45 | ちがいがわかるだろうか?このP2SHの`scriptPubKey`はマルチシグのスクリプトのハッシュを表している。これは`redeemScript.Hash.ScriptPubKey`と同値だ。 46 | 47 | ハッシュなので、簡単にbase58エンコードの`BitcoinScriptAddress`に変換できる。 48 | 49 | ```cs 50 | Key bob = new Key(); 51 | Key alice = new Key(); 52 | Key satoshi = new Key(); 53 | 54 | Script redeemScript = 55 | PayToMultiSigTemplate 56 | .Instance 57 | .GenerateScriptPubKey(2, new[] { bob.PubKey, alice.PubKey, satoshi.PubKey }); 58 | //Console.WriteLine(redeemScript.Hash.ScriptPubKey); 59 | Console.WriteLine(redeemScript.Hash.GetAddress(Network.Main)); // 3E6RvwLNfkH6PyX3bqoVGKzrx2AqSJFhjo 60 | ``` 61 | 62 | このようなアドレスはどのクライアントのウォレットも認識する。そのウォレットが「マルチシグ」とはなにかを理解していないとしてもだ。 63 | 64 | P2SHを使う支払いでは、ハッシュを得た`scriptPubKey`のことを **Redeem Script** と呼んでいる。 65 | 66 | ![](../assets/RedeemScript.png) 67 | 68 | 支払う人は **Redeem Scriptのハッシュ** についてだけ知っていれば良いから、**Redeem Script** を知ることはない。だから今のケースでは支払い者はビットコインを送金した先がボブ、サトシまたはアリスのマルチシグだということさえ知らないのだ。 69 | 70 | このようなトランザクションに署名することは前の章(Bitcoin transferの章)で実践したものと似ている。1つだけちがいがあるのは、トランザクションを **TransactionBuilder** で生成するときは **Redeem Script** を生成しなければならないということだ。 71 | 72 | マルチシグのP2SHがコインを受け取って、`received`というトランザクションにあると想定しよう。 73 | 74 | ```cs 75 | Script redeemScript = 76 | PayToMultiSigTemplate 77 | .Instance 78 | .GenerateScriptPubKey(2, new[] { bob.PubKey, alice.PubKey, satoshi.PubKey }); 79 | ////Console.WriteLine(redeemScript.Hash.ScriptPubKey); 80 | //Console.WriteLine(redeemScript.Hash.GetAddress(Network.Main)); 81 | 82 | Transaction received = new Transaction(); 83 | //Pay to the script hash 84 | received.Outputs.Add(new TxOut(Money.Coins(1.0m), redeemScript.Hash)); 85 | ``` 86 | 87 | > 注意:この支払いは`redeemScript`ではなく`redeemScript.Hash`に送っているから注意! 88 | 89 | そしてアリス、ボブまたはサトシが受け取ったビットコインを使いたいときは、`Coin`クラスのインスタンスを生成するのではなく、`ScriptCoin`クラスのインスタンスを生成する。 90 | 91 | ```cs 92 | //Give the redeemScript to the coin for Transaction construction 93 | //and signing 94 | ScriptCoin coin = received.Outputs.AsCoins().First() 95 | .ToScriptCoin(redeemScript); 96 | ``` 97 | 98 | ![](../assets/ScriptCoin.png) 99 | 100 | あとに続くトランザクションを生成して署名するコードは、マルチシグそのものを使ったトランザクションを説明した前章のコードとまったく同じである。 101 | -------------------------------------------------------------------------------- /other_types_of_ownership/p2w_over_p2sh.md: -------------------------------------------------------------------------------- 1 | ## P2W\* over P2SH {#p2w-over-p2sh} 2 | 3 | ビットコインの要求をスクリプト化するための **witness scriptPubKey** を使うことが魅力的だと思われてきている一方で、実際最近のウォレットのほとんどは、P2PKHあるいはP2SHしかサポートしていない。 4 | 5 | 古いソフトウェアが共存している間、segwitの利点を利用するために、P2SH上でP2Wを使うことができる。古いBitcoinCoreを使っているノードにとっては、それは普通のP2SHを利用した支払いと捉える。 6 | 7 | どんな **P2W\*** でも **P2SH上のP2W\*** に変換できる。以下の手順を踏む。 8 | 9 | 1. **ScriptPubKey** を、同じ内容を示すP2SHで置き換える 10 | 2. 変換前の **ScriptPubKey** はトランザクションインプットの **scriptSig** の中に1つだけのプッシュとして記録される。 11 | 3. すべての他のデータはトランザクションインプットのwitnessに示される。 12 | 13 | 心配しないでほしいのだが、もしこれが複雑だと思われたとしても、TransactionBuilderによって効果的にトランザクションを生成できる。 14 | 15 | P2SH上のP2WPKH、または略称では **P2SH\(P2WPKH\)** だが、例を見てみよう。 16 | 17 | **ScriptPubKey** を表示する。 18 | 19 | ```cs 20 | var key = new Key(); 21 | Console.WriteLine(key.PubKey.WitHash.ScriptPubKey.Hash.ScriptPubKey); 22 | ``` 23 | 24 | > 注意:これはとても畏怖の念を感じさせるコードだ。 25 | 26 | そうするとよく親しみのあるP2SHの **scriptPubKey** が表示される。 27 | 28 | ``` 29 | OP_HASH160 b19da5ca6e7243d4ec8eab07b713ff8768a44145 OP_EQUAL 30 | ``` 31 | 32 | そしてこのアウトプットを使う、署名されたトランザクションは以下のようになる。 33 | 34 | ```json 35 | "in": [ 36 | { 37 | "prev_out": { 38 | "hash": "674ece694e5e28956138efacab96fc0bffd7c6cc1af7bb2729943fedf8f0b8b9", 39 | "n": 0 40 | }, 41 | "scriptSig": "001404100ab485c95701bf0f4d73e3fe7d69ecc4f0ea", 42 | "witness": "3045022100f4c14cf383c0c97bbdaf520ea06f7db6c61e0effbc4bd3dfea036a90272f6cce022055b0fc058759a7961e718d48a3dc4dd5580fffc310557925a0865dbe467a835901 0205b956a5afe8f34a01337f0949f5733b5e376caaea57c9624e40e739a0b1d16c" 43 | } 44 | ], 45 | ``` 46 | 47 | **scriptSig** は先ほど出てきたScriptPubKey(言い換えると、**key.PubKey.WitHash.ScriptPubKey**)のP2SH化されたredeem scriptのプッシュでしかない。witnessは完全に通常の **P2WPKH** による支払いと同じになっている。 48 | 49 | NBitcoinでは、**P2SH\(P2WPKH\)** に署名することは、ScriptCoinを用いた通常のP2SHとほぼ同じようなものだ。 50 | 51 | 同じ原則に則って、**P2SH\(P2WSH\)** がどのように見えるかを見てみよう。この場合、2つの異なるredeem scriptを扱わなければならない。トランザクションインプットの **scriptSig** に入れる必要のある **P2SHのredeem script** と、witnessに入れる必要のある **P2WSHのredeem script** だ。 52 | 53 | 最初のルールにもとづいて、**scriptPubKey** を表示してみよう。 54 | 55 | 1. **ScriptPubKey** をP2SHと同等の情報で置き換える。 56 | 57 | ```cs 58 | var key = new Key(); 59 | Console.WriteLine(key.PubKey.ScriptPubKey.WitHash.ScriptPubKey.Hash.ScriptPubKey); 60 | ``` 61 | 62 | ``` 63 | OP_HASH160 d06c0058175952afecc56d26ed16558b1ed40e42 OP_EQUAL 64 | ``` 65 | 66 | > **注意**:理解できるから、ここでキレて回線切断しないで! 67 | 68 | 2. 置き換え前の **ScriptPubKey** はトランザクションインプットの **scriptSig** にたった1つのプッシュとして記録される。 69 | 70 | 3. すべての他のデータはトランザクションインプットのwitnessにプッシュされる。 71 | 72 | 項番3の「**他のデータ**」というのは、P2WSHにおける支払いの文脈では、**P2WSHのredeem script** のプッシュに続く、**P2WSHのredeem script** のパラメータを意味する。 73 | 74 | ```json 75 | "in": [ 76 | { 77 | "prev_out": { 78 | "hash": "1d23fa744a26cf6433f0841e9de7e088cf95e6f953e584b98d0de6ef4216765f", 79 | "n": 0 80 | }, 81 | "scriptSig": "0020c54eb79829b2e26b71d15fd3b490b6e95cbdab361a45eed2cdfe642497480a6c", 82 | "witness": "3045022100d7570c3bf87149a0be3ba2e8bfccbdd35c3da44f741695e9962014795fabc4fc02203183cfa55a85728520b0f1ac59ac3ffa1a8526634fe619f99fac0f76016f366e01 2103146e87d7fcc81f3e044f97c6b262c01826f40a9ab9acae0f689983a5890a1f4dac" 83 | } 84 | ], 85 | ``` 86 | 87 | 要約すると、P2SHのRedeem Scriptがハッシュされて、通常のP2WSHによる支払いとしてP2WSHのscriptPubKeyが得られる。そして通常のP2SHの支払いとして、P2WSHのscriptPubKeyはハッシュされて置き換わり、まさにP2SHを作るために使われる。 88 | 89 | もし、P2SH/P2WSH/P2SH\(P2WSH\)/P2SH\(P2WPKH\)が複雑に思えていても、怖がることはない。 90 | NBitcoinでは、**これらP2SHが関連するすべての支払い形式において**、**ScriptCoin** を作ることだけしか求めない。それは **P2SH** の章で説明したとおりで、P2WSHかP2SHのRedeem ScriptとScriptPubKeyを与えてやれば、作ることができる。 91 | 92 | NBitcoinに関して言えば、使いたいと思っているトランザクションアウトプットを使い、正しいredeem scriptがあれば、前章の「**マルチシグ**」の章で説明されたように、そして次の「**TransactionBuilderを使ってみる**」の章でも説明するが、**TransactionBuilder** が正しい署名の仕方を把握してくれる。 93 | 94 | ![](../assets/ScriptCoin.png) 95 | 96 | **P2SH/P2WSH/P2SH\(P2WSH\)/P2SH\(P2WPKH\)それぞれに互換性があるのだ。** 97 | 98 | P2WPKHまたはP2WSHの支払いの例をさらに見たい場合は、[http://n.bitcoin.ninja/checkscript](http://n.bitcoin.ninja/checkscript)で見られる。 99 | -------------------------------------------------------------------------------- /other_types_of_ownership/p2wpkh_pay_to_witness_public_key_hash.md: -------------------------------------------------------------------------------- 1 | ## P2WPKH \(Pay to Witness Public Key Hash\) {#p2wpkh-pay-to-witness-public-key-hash} 2 | 3 | 2015年、Peter Wuilleが **Segregated Witness**、略して **segwit** と呼ばれる新しい機能をビットコインに提案した。基本的には、Segregated Witnessは所有権の証明を、トランザクションの **scriptSig** から、トランザクションインプットの **witness** と呼ばれる新しい部分に移すものだ。 4 | 5 | この新しいスキームを使うことにはいくつかの理由があるが、ここには要点だけ述べるので詳細はこのリンクを見てほしい:[https://bitcoincore.org/en/2016/01/26/segwit-benefits/](https://bitcoincore.org/en/2016/01/26/segwit-benefits/) 6 | 7 | * **第三者によるトランザクション展性に関する課題解決**:以前は第三者が、トランザクションが承認される前にそのトランザクションIDを変えてしまうことが可能だったが、それが不可能になる。 8 | * **署名ハッシュの線形スケール**:トランザクションに署名とは、トランザクション全体を対象にしたハッシュ値計算を各インプットそれぞれに行うことである。これは大きいサイズのトランザクションを使うことで、DDOSベクター攻撃の危険性を持つが、それを防ぐことができる。 9 | * **トランザクションインプットの金額に署名する**:インプットの消費金額も署名の対象になる。それは署名者が支払う手数料を、間違えないことを意味する。 10 | * **キャパシティの向上**:10分ごとにトータル1MB以上(1.75MB程度まで)のトランザクション量に対応することができる。 11 | * **詐欺への防御**:後々開発される予定だが、SPVウォレットでは、今の最も長いチェーンが正当とするルールだけでなくさらに、コンセンサスルールを追加することができる。 12 | 13 | 以前はトランザクションの署名がトランザクションIDの計算対象に入っていたが、segwitではもうそれは入らない。 14 | 15 | ![](../assets/segwit.png) 16 | 17 | 署名はP2PKHでの支払いと同じ情報をもつが、scriptSigにではなく、witnessエリアに配置される。しかし、`scriptPubKey` は 18 | 19 | ``` 20 | OP_DUP OP_HASH160 0067c8970e65107ffbb436a49edd8cb8eb6b567f OP_EQUALVERIFY OP_CHECKSIG 21 | ``` 22 | 23 | ではなく、以下のようになる。 24 | 25 | ``` 26 | 0 0067c8970e65107ffbb436a49edd8cb8eb6b567f 27 | ``` 28 | 29 | アップグレードしていないノードにとっては、これはスタックに対しての2つのプッシュとしてしか見えない。これはどういうことかというと、どんな`scriptSig` でもそれらのビットコインを使えてしまうということだ。だから署名がなくても古いノードはどのトランザクションを有効とみなしてしまう。新しいノードは最初のプッシュを **witness バージョン** と解釈し、2番目のプッシュを **witness プログラム** とみなす。 30 | 31 | しかし新しいノードはトランザクションを検証するために署名を必要とする。 32 | 33 | **NBitcoinでは、P2WPKHのアウトプットを消費することは普通のP2PKHを使用する方法と同じである。 34 | 公開鍵から P2WHPKHで使う** `ScriptPubKey` **を取得するために、** `PubKey.Hash` **でなく** `PubKey.WitHash` **を使う。** 35 | 36 | ```cs 37 | var key = new Key(); 38 | Console.WriteLine(key.PubKey.WitHash.ScriptPubKey); 39 | ``` 40 | 41 | そうするとこのような出力がされるだろう。 42 | 43 | ``` 44 | 0 0067c8970e65107ffbb436a49edd8cb8eb6b567f 45 | ``` 46 | 47 | このようなビットコインを使用するための署名は「`TransactionBuilder`を使ってみる」で説明するが、P2PKHのアウトプットに署名するコードと何も変わらない。 48 | 49 | `witness`はP2PKHの`scriptSig`と同様で、`scriptSig`は空になる。 50 | 51 | ```json 52 | "in": [ 53 | { 54 | "prev_out": 55 | { 56 | "hash": "725497eaef527567a0a18b310bbdd8300abe86f82153a39d2f87fef713dc8177", 57 | "n": 0 58 | }, 59 | "scriptSig": "", 60 | "witness": "3044022079d443be2bd39327f92adf47a34e4b6ad7c82af182c71fe76ccd39743ced58cf0220149de3e8f11e47a989483f371d3799a710a7e862dd33c9bd842c417002a1c32901 0363f24cd2cb27bb35eb2292789ce4244d55ce580218fd81688197d4ec3b005a67" 61 | } 62 | ``` 63 | 64 | もう一度言うが、P2WPKHはP2PKHの文法と同じだ。ただ、署名がP2PKHの場合とは異なるところにセットされる。 65 | -------------------------------------------------------------------------------- /other_types_of_ownership/p2wsh_pay_to_witness_script_hash.md: -------------------------------------------------------------------------------- 1 | ## P2WSH \(Pay to Witness Script Hash\) {#p2wsh-pay-to-witness-script-hash} 2 | 3 | P2PKHとP2WPKHとの関係と同じで、P2SHとP2WSHとのちがいはP2SHにおける支払いで`scriptSig`に記録されていたものの場所と、生成される`scriptPubKey`だけだ。 4 | 5 | `scriptPubKey`は以下のように変わる。まずP2SHの形式は以下のとおり。 6 | 7 | `OP_HASH160 10f400e996c34410d02ae76639cbf64f4bdf2def OP_EQUAL` 8 | 9 | それからP2WSHでは以下のように変わる。 10 | 11 | `0 e4d3d21bab744d90cd857f56833252000ac0fade318136b713994b9319562467` 12 | 13 | 以下のコードでこのscriptPubKeyを導出できる。 14 | 15 | ```cs 16 | var key = new Key(); 17 | Console.WriteLine(key.PubKey.ScriptPubKey.WitHash.ScriptPubKey); 18 | ``` 19 | 20 | そしてP2SHで`scriptSig`(署名とredeem Scriptの合成)にあったものは、`witness`に移動する。 21 | 22 | ```json 23 | "in": [ 24 | { 25 | "prev_out": { 26 | "hash": "ffa2826ba2c9a178f7ced0737b559410364a62a41b16440beb299754114888c4", 27 | "n": 0 28 | }, 29 | "scriptSig": "", 30 | "witness": "304402203a4d9f42c190682826ead3f88d9d87e8c47db57f5c272637441bafe11d5ad8a302206ac21b2bfe831216059ac4c91ec3e4458c78190613802975f5da5d11b55a69c601 210243b3760ce117a85540d88fa9d3d605338d4689bed1217e1fa84c78c22999fe08ac" 31 | } 32 | ] 33 | ``` 34 | 35 | P2SHの支払いで説明したとおり、P2WSHでもまったく同様で署名するときは`ScriptCoin`クラスを使う。 36 | 37 | -------------------------------------------------------------------------------- /other_types_of_ownership/using_the_transactionbuilder.md: -------------------------------------------------------------------------------- 1 | ## TransactionBuilderを使ってみる {#using-the-transactionbuilder} 2 | 3 | あなたにとって初めての **P2SH** や **マルチシグ** のトランザクションに署名するときに **TranasctionBuilder** をどのように動かすか見てきた。 4 | 5 | 次はより複雑なトランザクションに対して署名するために、そのフルパワーをどのように活かすかを見てみよう。 6 | 7 | **TranactionBuilder** を用いると以下ができるようになる。 8 | 9 | * 以下の支払いができる 10 | * **P2PK**、**P2PKH** 11 | * **マルチシグ** 12 | * **P2WPK**、**P2WSH** 13 | * 前章のようにredeem scriptにもとづいて、**P2SH** を支払いに使える 14 | * **ステルスコイン** を使える(ダークウォレット) 15 | * **カラードコイン** を発行し、移動できる(次の章で説明するオープンアセットのこと) 16 | * **部分的に署名されたトランザクション** を結合できる 17 | * **署名されていないトランザクション** の最終的な **サイズ** とそれにかかる **手数料** を計算できる 18 | * **トランザクション** が **十分に署名されたか** を確認できる 19 | 20 | **TransactionBuilder** のゴールはインプットとしての **コイン** と **鍵** を取得し、**十分に** または **部分的に署名されたトランザクション** を生成することである。 21 | 22 | ![](../assets/SignedTransaction.png) 23 | 24 | **TransactionBuilder** だけで、どの **コイン** を使い、なにを署名すべきかを把握してくれる。 25 | 26 | ![](../assets/TransactionBuilder.png) 27 | 28 | TransactionBuilderを使うためには4つのステップがある。 29 | 30 | * 使う **コイン** を集める 31 | * 持っている **鍵** を集める 32 | * どの **scriptPubKey** に対していくら **コインを** 支払いたいかを数える 33 | * **トランザクション** を生成して署名する 34 | * **オプション**:誰かに **トランザクション** を送り、署名してもらうか生成を続けてもらう 35 | 36 | さあ **コイン** を集めてみよう。まずそのコインを充足させるために見せかけの **トランザクション** を作ろう。 37 | ここでは、その **トランザクション** には **P2PKH**、**P2PK** と、ボブとアリスの **マルチシグに** コインがあることにしよう。 38 | 39 | ```cs 40 | // Create a fake transaction 41 | var bob = new Key(); 42 | var alice = new Key(); 43 | 44 | Script bobAlice = 45 | PayToMultiSigTemplate.Instance.GenerateScriptPubKey( 46 | 2, 47 | bob.PubKey, alice.PubKey); 48 | 49 | var init = new Transaction(); 50 | init.Outputs.Add(new TxOut(Money.Coins(1m), bob.PubKey)); // P2PK 51 | init.Outputs.Add(new TxOut(Money.Coins(1m), alice.PubKey.Hash)); // P2PKH 52 | init.Outputs.Add(new TxOut(Money.Coins(1m), bobAlice)); 53 | ``` 54 | 55 | さらにここではサトシに支払うためにこのトランザクションの`coins`を使いたいということにしよう。 56 | 57 | ```cs 58 | var satoshi = new Key(); 59 | ``` 60 | 61 | まずは **コイン** を集めなければならない。 62 | 63 | ```cs 64 | Coin[] coins = init.Outputs.AsCoins().ToArray(); 65 | Coin bobCoin = coins[0]; 66 | Coin aliceCoin = coins[1]; 67 | Coin bobAliceCoin = coins[2]; 68 | ``` 69 | 70 | では`bob`は0.2BTC、`alice`は0.3BTCを送り、さらに2人が0.5BTCを送るために`bobAlice`を使うことに合意したとしよう。 71 | 72 | ```cs 73 | var builder = new TransactionBuilder(); 74 | Transaction tx = builder 75 | .AddCoins(bobCoin) 76 | .AddKeys(bob) 77 | .Send(satoshi, Money.Coins(0.2m)) 78 | .SetChange(bob) 79 | .Then() 80 | .AddCoins(aliceCoin) 81 | .AddKeys(alice) 82 | .Send(satoshi, Money.Coins(0.3m)) 83 | .SetChange(alice) 84 | .Then() 85 | .AddCoins(bobAliceCoin) 86 | .AddKeys(bob, alice) 87 | .Send(satoshi, Money.Coins(0.5m)) 88 | .SetChange(bobAlice) 89 | .SendFees(Money.Coins(0.0001m)) 90 | .BuildTransaction(sign: true); 91 | ``` 92 | 93 | そしてトランザクションが十分に署名され、ネットワークに送る準備ができているかを確かめることができる。 94 | 95 | ```cs 96 | Console.WriteLine(builder.Verify(tx)); // True 97 | ``` 98 | 99 | このモデルで素晴らしいのは、**ScriptCoin** を作る必要があることを除いて、**P2SH、P2WSH、P2SH\(P2WSH\)とP2SH\(P2PKH\)** に対して同じ方法で動かすことができるのだ。 100 | 101 | ![](../assets/ScriptCoinFromCoin.png) 102 | 103 | ```cs 104 | init = new Transaction(); 105 | init.Outputs.Add(new TxOut(Money.Coins(1.0m), bobAlice.Hash)); 106 | 107 | coins = init.Outputs.AsCoins().ToArray(); 108 | ScriptCoin bobAliceScriptCoin = coins[0].ToScriptCoin(bobAlice); 109 | ``` 110 | 111 | 署名はこのようにする。 112 | 113 | ```cs 114 | builder = new TransactionBuilder(); 115 | tx = builder 116 | .AddCoins(bobAliceScriptCoin) 117 | .AddKeys(bob, alice) 118 | .Send(satoshi, Money.Coins(0.9m)) 119 | .SetChange(bobAlice.Hash) 120 | .SendFees(Money.Coins(0.0001m)) 121 | .BuildTransaction(true); 122 | Console.WriteLine(builder.Verify(tx)); // True 123 | ``` 124 | 125 | **ステルスコイン** でも、基本的には同じだ。ただ、ダークウォレットについての紹介をもし覚えていたら、**ステルスコイン** を見るためには **ScanKey** が必要となると言ったが、それが異なる点となる。 126 | 127 | ![](../assets/StealthCoin.png) 128 | 129 | 以前の章と同じように、アリスとボブのマルチシグのステルスアドレスを作ってみよう。 130 | 131 | ```cs 132 | Key scanKey = new Key(); 133 | BitcoinStealthAddress darkAliceBob = 134 | new BitcoinStealthAddress 135 | ( 136 | scanKey: scanKey.PubKey, 137 | pubKeys: new[] { alice.PubKey, bob.PubKey }, 138 | signatureCount: 2, 139 | bitfield: null, 140 | network: Network.Main 141 | ); 142 | ``` 143 | 144 | 誰かがこのトランザクションにコインを送ったとしよう。 145 | 146 | ```cs 147 | //Someone sent to darkAliceBob 148 | init = new Transaction(); 149 | darkAliceBob 150 | .SendTo(init, Money.Coins(1.0m)); 151 | ``` 152 | 153 | scanKeyを持っている人がこのステルスコインを発見できる。 154 | 155 | ```cs 156 | //Get the stealth coin with the scanKey 157 | StealthCoin stealthCoin 158 | = StealthCoin.Find(init, darkAliceBob, scanKey); 159 | ``` 160 | 161 | それはボブとアリスに送られており、彼らが署名する。 162 | 163 | ```cs 164 | //Spend it 165 | tx = builder 166 | .AddCoins(stealthCoin) 167 | .AddKeys(bob, alice, scanKey) 168 | .Send(satoshi, Money.Coins(0.9m)) 169 | .SetChange(bobAlice.Hash) 170 | .SendFees(Money.Coins(0.0001m)) 171 | .BuildTransaction(true); 172 | Console.WriteLine(builder.Verify(tx)); // True 173 | ``` 174 | 175 | > **注釈**:ステルスコインを使うためにはscanKeyが必要だ。 176 | -------------------------------------------------------------------------------- /second_communitry_edition.md: -------------------------------------------------------------------------------- 1 | # 第2(コミュニティ)版 {#second-community-edition} 2 | 3 | \([nopara73](https://github.com/nopara73)\) 2013年に私はビットコインに夢中になった。そのときはあらゆる人が、開発者にビットコインは数え切れない素晴らしい機会を与えてくれると話していたが、私はまったく理解が追いつかなかった。 4 | コーディングを試みるといつも、数え切れない壁、抜け落ちたピースととんでもない量の負荷に遭遇した。それを乗り越えないと、自分のアイディアに取り掛かるのを始めることさえできなかった。 5 | 6 | 数年後、嬉しいことに私が話していた仕事をすでにやり遂げている人がいることに気づいた。 7 | その人はついに暗号の魔法をオブジェクト指向にきれいに分類していたのだ。さらに私が興奮したのは、Nicolas DorierのC\#のライブラリが、世にある中で最も網羅的で完璧なビットコインライブラリで、あらゆるプラットフォームで動作することに気づいた。さらに、彼はライブラリに関する本までも書いているではないか!だから今私は、お気に入りのプログラミング言語で書かれ随時更新もされている、最もパワフルでしっかりとドキュメント化されたビットコインライブラリを使って働くチャンスを得ている。 8 | 9 | しかし私の興奮、ビットコインへの中毒、そしてリスクを好む性格は私をここで止まらせなかった。Nicolasに連絡を取り、積もる話は省くと、一ヶ月前に気づいたら飛行機で東京に向かっていた。完全にビットコイン業界に没頭するためにだ。そして貯金がなくなり、仕事を見つけなければならなくなるまでずっと、Nicolasの教えのもとに学んだ。 10 | その結果できあがったのがこの本のセカンドエディションと、かなり散らかった部屋だ。なんたって自分の荷物を開けている時間すらなかったのだ。さらに驚いたのは自分が結構きれい好きだと気づいたことだ。 11 | 12 | 話を本に戻そう。初版と比較すると、Nicolasの最新の仕事を紹介することによって本を最新化し、一連の誤字を修正し(同じくらい誤字を残してはいるが)、たくさんの人が理解できるように多くの箇所で詳細化して、本をGitHubとGitbookにアップロードした。だからこそ今、コミュニティ全体が本の改善に関わることができるだろう。 13 | 14 | もしこの本を一文で表さなければならないとしたらこれだろう。「**ビットコインを語るのではなく、ビットコインをやろう!**」 15 | 16 | -------------------------------------------------------------------------------- /security/protecting_your_private_keys.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingBlockchain/ProgrammingBlockchain-Japanese/70652855c64b23ffe43d562fcfdefbdbdef92585/security/protecting_your_private_keys.md --------------------------------------------------------------------------------