├── .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 ├── segwit.png └── visualstudio_enablesourceserversupport.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 /.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 | [Click here for code examples](https://github.com/ProgrammingBlockchain/ProgrammingBlockchainCodeExamples/) 4 | ## [Click here to read the book](https://programmingblockchain.gitbooks.io/programmingblockchain/content/) 5 | 6 | ## Community 7 | [![Gitter](https://badges.gitter.im/MetacoSA/NBitcoin.svg)](https://gitter.im/MetacoSA/NBitcoin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 8 | 9 | ## Other languages 10 | Indonesian: [Read](https://nopara73.gitbooks.io/programmingblockchainindonesian/content/) - [GitHub](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain-Indonesian) - [GitBook](https://www.gitbook.com/book/nopara73/programmingblockchainindonesian) 11 | 12 | ## Quick feedback 13 | If you notice any mistakes, and don't want to fix them yourself, open an issue [on the Github page of the book.](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain) 14 | If you are reading this book with GitBook, you can also create a quick inline comment. 15 | 16 | ## How can I fix a typo? Aka quick contribution 17 | 1. Find [the book on Github](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain) 18 | 2. Fork 19 | 3. Edit file 20 | 4. Make a pull request 21 | 22 | ## How can I write a new chapter? Aka extensive contribution 23 | 1. Find [the book on Github](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain) 24 | 2. Fork 25 | 3. Clone your fork 26 | 4. Download and install [Gitbook editor](https://www.gitbook.com/) 27 | 5. Open Gitbook editor 28 | 6. Select "Import" and select the folder where you cloned your fork 29 | 7. Edit book 30 | 8. Save files and Sync 31 | 9. Make a pull request 32 | 33 | ## Enhancing your learning process 34 | Making contributions while you are reading is a good way to learn faster. If you have a hard time understanding something, try to reword it and make a pull request for other readers. 35 | 36 | You can also help [fixing issues](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain/issues). (Protip for university students: a good GitHub profile is more valuable than a diploma in the job market.) 37 | 38 | ## How to feed us 39 | For every donation on this address, you will appear on [http://n.bitcoin.ninja/](http://n.bitcoin.ninja/). 40 | 41 | ![1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB](assets/BookQr.png) 42 | 43 | [1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB](https://www.smartbit.com.au/address/1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB) 44 | 45 | ## Links 46 | 47 | [The book on GitHub](https://github.com/ProgrammingBlockchain/ProgrammingBlockchain) 48 | [The book on GitBook](https://www.gitbook.com/book/programmingblockchain/programmingblockchain) (You can download pdf, epub, mobi versions here.) 49 | [Code examples on GitHub](https://github.com/ProgrammingBlockchain/ProgrammingBlockchainCodeExamples/) 50 | [Hall of the Makers](http://n.bitcoin.ninja/) (Here are the true makers those succeeded to complete the challenges of this book.) 51 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [README](README.md) 4 | * [Foreword](foreword.md) 5 | * [Second (Community) Edition](second_communitry_edition.md) 6 | * [Introduction](introduction/README.md) 7 | * [Why Blockchain Programming and not Bitcoin Programming?](introduction/why_blockchain_programming_and_not_bitcoin_program.md) 8 | * [Why C#?](introduction/why_c.md) 9 | * [Why this book?](introduction/why_do_people_hate_bitcoin.md) 10 | * [Crowdfunding this book](introduction/crowdfunding_this_book.md) 11 | * [Complementary Reading](introduction/complementary_reading.md) 12 | * [Diagrams](introduction/diagrams.md) 13 | * [License: CC (ASA 3U)](introduction/license_cc_asa_3u.md) 14 | * [Pre-requisites](introduction/pre-requisites.md) 15 | * [Project Setup](introduction/project_setup.md) 16 | * [Bitcoin transfer](bitcoin_transfer/README.md) 17 | * [Bitcoin address](bitcoin_transfer/bitcoin_address.md) 18 | * [ScriptPubKey](bitcoin_transfer/payment_script.md) 19 | * [Private key](bitcoin_transfer/private_key.md) 20 | * [Transaction](bitcoin_transfer/transaction.md) 21 | * [Blockchain](bitcoin_transfer/blockchain.md) 22 | * [“The Blockchain is more than just Bitcoin”](bitcoin_transfer/the_blockchain_is_more_than_just_bitcoin.md) 23 | * [Spend your coin](bitcoin_transfer/spend_your_coin.md) 24 | * [Proof of ownership as an authentication method](bitcoin_transfer/proof_of_ownership_as_an_authentication_method.md) 25 | * [Key generation and encryption](key_generation/key_generation.md) 26 | * [Is it random enough?](key_generation/key_generation.md#is-it-random-enough) 27 | * [Key Derivation Function](key_generation/key_generation.md#key-derivation-function) 28 | * [Like the good ol’ days](key_generation/key_generation.md#like-the-good-ol-days) 29 | * [BIP38 (Part 2)](key_generation/key_generation.md#bip38-part-2) 30 | * [HD Wallet (BIP 32)](key_generation/key_generation.md#hd-wallet-bip-32) 31 | * [Mnemonic Code for HD Keys (BIP39)](key_generation/key_generation.md#mnemonic-code-for-hd-keys-bip39) 32 | * [Dark Wallet](key_generation/key_generation.md#dark-wallet) 33 | * [Other types of ownership](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 | * [Multi Sig](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 | * [Arbitrary](other_types_of_ownership/arbitrary.md) 41 | * [Using the TransactionBuilder](other_types_of_ownership/using_the_transactionbuilder.md) 42 | * [Other types of asset](other_types_of_asset/README.md) 43 | * [Colored Coins](other_types_of_asset/colored_coins.md) 44 | * [Issuing an Asset](other_types_of_asset/issuing_an_asset.md) 45 | * [Transfer an Asset](other_types_of_asset/transfer_an_asset.md) 46 | * [Unit tests](other_types_of_asset/unit_tests.md) 47 | * [Ricardian contracts](other_types_of_asset/ricardian_contracts.md) 48 | * [Liquid Democracy](other_types_of_asset/liquid_democracy.md) 49 | * [Proof of Burn and Reputation](other_types_of_asset/proof_of_burn_and_reputation.md) 50 | * [Protecting your private keys](security/protecting_your_private_keys.md) 51 | * [Case studies](implementations/README.md) 52 | * [HiddenBitcoin: Managing keys](implementations/hiddenbitcoinkey_storage_hd_wallet_md.md) 53 | 54 | -------------------------------------------------------------------------------- /assets/BitcoinAddress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/BitcoinAddress.png -------------------------------------------------------------------------------- /assets/BitcoinAddressToScriptPubKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/BitcoinAddressToScriptPubKey.png -------------------------------------------------------------------------------- /assets/BitcoinCoreTransaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/BitcoinCoreTransaction.png -------------------------------------------------------------------------------- /assets/BitcoinSecret.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/BitcoinSecret.png -------------------------------------------------------------------------------- /assets/BookQr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/BookQr.png -------------------------------------------------------------------------------- /assets/CeoMarketingAccounting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/CeoMarketingAccounting.png -------------------------------------------------------------------------------- /assets/Coinprism.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/Coinprism.png -------------------------------------------------------------------------------- /assets/Coinprism2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/Coinprism2.png -------------------------------------------------------------------------------- /assets/ColorMaker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ColorMaker.png -------------------------------------------------------------------------------- /assets/ColoredCoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ColoredCoin.png -------------------------------------------------------------------------------- /assets/ColoredTransaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ColoredTransaction.png -------------------------------------------------------------------------------- /assets/Derive1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/Derive1.png -------------------------------------------------------------------------------- /assets/Derive2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/Derive2.png -------------------------------------------------------------------------------- /assets/DeriveKeyPath.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/DeriveKeyPath.png -------------------------------------------------------------------------------- /assets/EncryptedKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/EncryptedKey.png -------------------------------------------------------------------------------- /assets/EncryptedKeyResult.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/EncryptedKeyResult.png -------------------------------------------------------------------------------- /assets/EphemKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/EphemKey.png -------------------------------------------------------------------------------- /assets/ExtKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ExtKey.png -------------------------------------------------------------------------------- /assets/ExtPubKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ExtPubKey.png -------------------------------------------------------------------------------- /assets/FetchColors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/FetchColors.png -------------------------------------------------------------------------------- /assets/FetchColors2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/FetchColors2.png -------------------------------------------------------------------------------- /assets/IColoredCoinTransactionRepository.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/IColoredCoinTransactionRepository.png -------------------------------------------------------------------------------- /assets/NicoWallet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/NicoWallet.png -------------------------------------------------------------------------------- /assets/NonHardened.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/NonHardened.png -------------------------------------------------------------------------------- /assets/OutPoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/OutPoint.png -------------------------------------------------------------------------------- /assets/PPKH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PPKH.png -------------------------------------------------------------------------------- /assets/PassphraseCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PassphraseCode.png -------------------------------------------------------------------------------- /assets/PassphraseCodeToEncryptedKeys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PassphraseCodeToEncryptedKeys.png -------------------------------------------------------------------------------- /assets/Power2Alice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/Power2Alice.png -------------------------------------------------------------------------------- /assets/PowerCoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PowerCoin.png -------------------------------------------------------------------------------- /assets/PowerCoin2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PowerCoin2.png -------------------------------------------------------------------------------- /assets/PowerCoin3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PowerCoin3.png -------------------------------------------------------------------------------- /assets/PowerCoin4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PowerCoin4.png -------------------------------------------------------------------------------- /assets/PowerCoin5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PowerCoin5.png -------------------------------------------------------------------------------- /assets/PrivKeyPubKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PrivKeyPubKey.png -------------------------------------------------------------------------------- /assets/PrivateKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PrivateKey.png -------------------------------------------------------------------------------- /assets/ProgrammingBlockchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ProgrammingBlockchain.png -------------------------------------------------------------------------------- /assets/PubKeyHashToBitcoinAddress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PubKeyHashToBitcoinAddress.png -------------------------------------------------------------------------------- /assets/PubKeyToAddr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PubKeyToAddr.png -------------------------------------------------------------------------------- /assets/PubKeyToScriptPubKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/PubKeyToScriptPubKey.png -------------------------------------------------------------------------------- /assets/QBitNuGet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/QBitNuGet.png -------------------------------------------------------------------------------- /assets/RawTx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/RawTx.png -------------------------------------------------------------------------------- /assets/ReceiverStealth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ReceiverStealth.png -------------------------------------------------------------------------------- /assets/RedeemScript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/RedeemScript.png -------------------------------------------------------------------------------- /assets/RootKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/RootKey.png -------------------------------------------------------------------------------- /assets/ScannerRecover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ScannerRecover.png -------------------------------------------------------------------------------- /assets/ScriptCoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ScriptCoin.png -------------------------------------------------------------------------------- /assets/ScriptCoinFromCoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ScriptCoinFromCoin.png -------------------------------------------------------------------------------- /assets/ScriptPubKey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ScriptPubKey.png -------------------------------------------------------------------------------- /assets/SignedTransaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/SignedTransaction.png -------------------------------------------------------------------------------- /assets/SpendTx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/SpendTx.png -------------------------------------------------------------------------------- /assets/StealthAddress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/StealthAddress.png -------------------------------------------------------------------------------- /assets/StealthCoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/StealthCoin.png -------------------------------------------------------------------------------- /assets/StealthMetadata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/StealthMetadata.png -------------------------------------------------------------------------------- /assets/ThirdPartyKeyGeneration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ThirdPartyKeyGeneration.png -------------------------------------------------------------------------------- /assets/TransactionBuilder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/TransactionBuilder.png -------------------------------------------------------------------------------- /assets/TransparentWallet2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/TransparentWallet2.png -------------------------------------------------------------------------------- /assets/Trezor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/Trezor.png -------------------------------------------------------------------------------- /assets/TxIn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/TxIn.png -------------------------------------------------------------------------------- /assets/TxOut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/TxOut.png -------------------------------------------------------------------------------- /assets/Visio/BIP32.vsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/Visio/BIP32.vsd -------------------------------------------------------------------------------- /assets/aliceSigned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/aliceSigned.png -------------------------------------------------------------------------------- /assets/bitcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/bitcoin.png -------------------------------------------------------------------------------- /assets/bobSigned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/bobSigned.png -------------------------------------------------------------------------------- /assets/ccasa3u.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/ccasa3u.png -------------------------------------------------------------------------------- /assets/coin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/coin.png -------------------------------------------------------------------------------- /assets/encrypted_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/encrypted_key.png -------------------------------------------------------------------------------- /assets/fullySigned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/fullySigned.png -------------------------------------------------------------------------------- /assets/nuget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/nuget.png -------------------------------------------------------------------------------- /assets/segwit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/segwit.png -------------------------------------------------------------------------------- /assets/visualstudio_enablesourceserversupport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratisproject/BlockchainProgramming/54b6f2d7fe47a15ae91751db313ecb2643216ccd/assets/visualstudio_enablesourceserversupport.png -------------------------------------------------------------------------------- /bitcoin_transfer/README.md: -------------------------------------------------------------------------------- 1 | # Stratis transfer {#Stratis-transfer} 2 | In Stratis, everything is designed to make sure that the transactions go through. In this chapter we are going to introduce the basic concepts of Stratis by guiding you through a creation of simple Stratis transaction "by hand". 3 | Later we are going to show you a higher level framework for building transactions. 4 | -------------------------------------------------------------------------------- /bitcoin_transfer/bitcoin_address.md: -------------------------------------------------------------------------------- 1 | ## Stratis address {#stratis-address} 2 | 3 | You know that your **Stratis Address** is what you share to the world to get paid. 4 | ![](../assets/StratisAddress.png) 5 | You probably know that your wallet software uses a **private key** to spend the money you received on this address. 6 | ![](../assets/PrivateKey.png) 7 | 8 | The keys are not stored on the network and they can be generated without access to the Internet. 9 | 10 | With code: 11 | ```cs 12 | Key privateKey = new Key(); // generate a random private key 13 | ``` 14 | From the private key, we use a one-way cryptographic function, to generate a **public key**. 15 | 16 | ![](../assets/PrivKeyPubKey.png) 17 | ```cs 18 | PubKey publicKey = privateKey.PubKey; 19 | Console.WriteLine(publicKey); // 0251036303164f6c458e9f7abecb4e55e5ce9ec2b2f1d06d633c9653a07976560c 20 | ``` 21 | 22 | There are two Stratis **networks**: 23 | * **TestNet** is a Stratis network for development purposes. Stratis on this network worth nothing. 24 | * **MainNet** is the Stratis network everybody uses. 25 | 26 | > **Note:** You can acquire testnet coins quickly by using **faucets**, just google "get testnet stratis". 27 | 28 | You can easily get your **stratis address** from your public key and the **network** on which this address should be used. 29 | 30 | ![](../assets/PubKeyToAddr.png) 31 | 32 | ```cs 33 | Console.WriteLine(publicKey.GetAddress(Network.Main)); // 1PUYsjwfNmX64wS368ZR5FMouTtUmvtmTY 34 | Console.WriteLine(publicKey.GetAddress(Network.TestNet)); // n3zWAo2eBnxLr3ueohXnuAa8mTVBhxmPhq 35 | ``` 36 | 37 | **Precisely a stratis address is made up by a version byte (different on both networks) and your public key’s hash bytes concatenated then encoded into Base58Check:** 38 | 39 | ![](../assets/PubKeyHashToBitcoinAddress.png) 40 | 41 | ```cs 42 | var publicKeyHash = publicKey.Hash; 43 | Console.WriteLine(publicKeyHash); // f6889b21b5540353a29ed18c45ea0031280c42cf 44 | var mainNetAddress = publicKeyHash.GetAddress(Network.Main); 45 | var testNetAddress = publicKeyHash.GetAddress(Network.TestNet); 46 | ``` 47 | 48 | > **Fact:** The hash of the public key is generated by performing a SHA256 hash on the public key, and then performing a RIPEMD160 hash on the result, with Big Endian notation. The function could look like this: RIPEMD160(SHA256(pubkey)) 49 | 50 | The Base58Check encoding has some neat features, such as checksums to prevent typos and a lack of ambiguous characters such as '0' and 'O'. 51 | The Base58Check encoding of an address also make sure that a user of a stratis wallet don't send money to an address that should be used in a different network. 52 | 53 | ```cs 54 | Console.WriteLine(mainNetAddress); // 1PUYsjwfNmX64wS368ZR5FMouTtUmvtmTY 55 | Console.WriteLine(testNetAddress); // n3zWAo2eBnxLr3ueohXnuAa8mTVBhxmPhq 56 | ``` 57 | 58 | > **Tip:** Practicing Stratis Programming on MainNet makes mistakes more memorable. 59 | -------------------------------------------------------------------------------- /bitcoin_transfer/blockchain.md: -------------------------------------------------------------------------------- 1 | ## Blockchain {#blockchain} 2 | 3 | You might have noticed that while we proved ownership of the spent TxOut, and that we have not proven the TxOut actually exists. This is where the main function of the Blockchain shines: 4 | 5 | The Blockchain is the database of all transactions that have happened since the the first Bitcoin transaction, known as the Genesis block. The Blockchain is duplicated all around the world. If you use Bitcoin Core, you have the whole Blockchain on your computer. Once a transaction appears on the Blockchain, it is very easy to prove its existence. 6 | 7 | **Miners** are entities whose only goal is to insert a transaction in The Blockchain. However miners do not modify the blockchain everytime they receive one transaction. Instead each of them try to add a whole batch of transaction at the same time known as a **block**. Other nodes on the network confirm the new block obeys the rules set forth in the Bitcoin protocol. If two miners add a block at the same time, we have a **fork**, ultimately only the branch of the fork with the most **work** will be continued. If a miner tries to include an invalid transaction in his block, the other nodes will not recognize it and the miner loses the investment spent on creating the block. 8 | 9 | Once a miner manages to submit a valid block all transactions inside are considered **Confirmed**. When this happens all miners must discard their current work and begin with new transactions. When a block is confirmed it is written into the Blockchain, and the likelihood of it being undone decreases dramatically with every subsequent block. 10 | 11 | For the first time in history we have a database which can’t easily be rewritten, eliminates the need for trust, resists censorship, and is widely distributed. Comparing the Blockchain to a ledger is only relevant if we consider Bitcoin as a currency. 12 | 13 | The Blockchain is a database, and you give meaning to its data. As you will soon discover, a bitcoin transaction can bear more information than just bitcoin transfers. A bitcoin transaction is a row in a database that can never be erased. 14 | 15 | As a user, you can verify that a specific transaction exists in the Blockchain in two different ways: 16 | 17 | * Check the entire Blockchain, which at the time of this writing is several gigabytes in size. 18 | * Ask for a partial merkel tree, which are a few kilobytes. We will talk about merkel trees more as it relates to Simple Payment Verification. 19 | -------------------------------------------------------------------------------- /bitcoin_transfer/payment_script.md: -------------------------------------------------------------------------------- 1 | ## ScriptPubKey {#payment-script} 2 | You might not know that as far as the Blockchain is concerned, there is no such thing as a Stratis Address. Internally, the Stratis protocol identifies the recipient of stratis by a **ScriptPubKey**. 3 | 4 | ![](../assets/ScriptPubKey.png) 5 | A **ScriptPubKey** may looks like this: 6 | ```OP_DUP OP_HASH160 14836dbe7f38c5ac3d49e8d790af808a4ee9edcf OP_EQUALVERIFY OP_CHECKSIG``` 7 | 8 | It is a short script that explains what conditions must be met to claim ownership of stratis. We will go into the types of operations in a **ScriptPubKey** as we move through the lessons of this book. 9 | 10 | We are able to generate the ScriptPubKey from the Stratis Address. This is a step that all sratis clients do to translate the “human friendly” Stratis Address to the Blockchain readable address. 11 | 12 | ![](../assets/StratisAddressToScriptPubKey.png) 13 | 14 | ```cs 15 | var publicKeyHash = new KeyId("14836dbe7f38c5ac3d49e8d790af808a4ee9edcf"); 16 | 17 | var testNetAddress = publicKeyHash.GetAddress(Network.TestNet); 18 | var mainNetAddress = publicKeyHash.GetAddress(Network.Main); 19 | 20 | Console.WriteLine(mainNetAddress.ScriptPubKey); // OP_DUP OP_HASH160 14836dbe7f38c5ac3d49e8d790af808a4ee9edcf OP_EQUALVERIFY OP_CHECKSIG 21 | Console.WriteLine(testNetAddress.ScriptPubKey); // OP_DUP OP_HASH160 14836dbe7f38c5ac3d49e8d790af808a4ee9edcf OP_EQUALVERIFY OP_CHECKSIG 22 | ``` 23 | 24 | Notice the **ScriptPubKey** for testnet and mainnet address is the same? 25 | Notice the **ScriptPubKey** contains the hash of the public key? 26 | We will not go into the details yet, but note that the **ScriptPubKey** appears to have nothing to do with the Stratis Address, but it does show the hash of the public key. 27 | 28 | Stratis Addresses are composed of a version byte which identify the network where to use the address and the hash of a public key. So we can go backward and generate a stratis address from the **ScriptPubKey** and the network identifier. 29 | 30 | ```cs 31 | var paymentScript = publicKeyHash.ScriptPubKey; 32 | var sameMainNetAddress = paymentScript.GetDestinationAddress(Network.Main); 33 | Console.WriteLine(mainNetAddress == sameMainNetAddress); // True 34 | ``` 35 | 36 | It is also possible to retrieve the hash from the **ScriptPubKey** and generate a Stratis Address from it: 37 | 38 | ```cs 39 | var samePublicKeyHash = (KeyId) paymentScript.GetDestination(); 40 | Console.WriteLine(publicKeyHash == samePublicKeyHash); // True 41 | var sameMainNetAddress2 = new StratisPubKeyAddress(samePublicKeyHash, Network.Main); 42 | Console.WriteLine(mainNetAddress == sameMainNetAddress2); // True 43 | ``` 44 | 45 | > **Note:** A ScriptPubKey does not necessarily contain the hashed public key(s) permitted to spend the stratis. 46 | 47 | So now you understand the relationship between a Private Key, a Public Key, a Public Key Hash, a Stratis Address and a ScriptPubKey. 48 | 49 | In the remainder of this book, we will exclusively use **ScriptPubKey**. A Stratis Address is only a user interface concept. 50 | -------------------------------------------------------------------------------- /bitcoin_transfer/private_key.md: -------------------------------------------------------------------------------- 1 | ## Private key {#private-key} 2 | 3 | Private keys are often represented in Base58Check called a **Stratis Secret** (also known as **Wallet Import Format** or simply **WIF**), like Stratis Addresses. 4 | 5 | ![](../assets/StratisSecret.png) 6 | 7 | ```cs 8 | Key privateKey = new Key(); // generate a random private key 9 | StratisSecret mainNetPrivateKey = privateKey.GetStratisSecret(Network.Main); // get our private key for the mainnet 10 | StratisSecret testNetPrivateKey = privateKey.GetStratisSecret(Network.TestNet); // get our private key for the testnet 11 | Console.WriteLine(mainNetPrivateKey); // L5B67zvrndS5c71EjkrTJZ99UaoVbMUAK58GKdQUfYCpAa6jypvn 12 | Console.WriteLine(testNetPrivateKey); // cVY5auviDh8LmYUW8AfafseD6p6uFoZrP7GjS3rzAerpRKE9Wmuz 13 | 14 | bool WifIsStratisSecret = mainNetPrivateKey == privateKey.GetWif(Network.Main); 15 | Console.WriteLine(WifIsBitcoinSecret); // True 16 | ``` 17 | 18 | Note that it is easy to go from **StratisSecret** to private **Key**. On the other hand, it is impossible to go from a Stratis Address to Public Key because the Stratis Address contains a hash of the Public Key, not the Public Key itself. 19 | Process this information by examining the similarities between these two codeblocks: 20 | 21 | ```cs 22 | Key privateKey = new Key(); // generate a random private key 23 | StratisSecret StratisSecret = privateKey.GetWif(Network.Main); // L5B67zvrndS5c71EjkrTJZ99UaoVbMUAK58GKdQUfYCpAa6jypvn 24 | Key samePrivateKey = StratisSecret.PrivateKey; 25 | Console.WriteLine(samePrivateKey == privateKey); // True 26 | ``` 27 | 28 | ```cs 29 | PubKey publicKey = privateKey.PubKey; 30 | StratisPubKeyAddress StratisPubicKey = publicKey.GetAddress(Network.Main); // 1PUYsjwfNmX64wS368ZR5FMouTtUmvtmTY 31 | //PubKey samePublicKey = StratisPubicKey.ItIsNotPossible; 32 | ``` 33 | 34 | ### Exercise: 35 | 1. Generate a private key on the mainnet and note it. 36 | 2. Get the corresponding address. 37 | 3. Send Stratis to it. As much as you cannot afford to lose, so it will keep you focused and motivated to get them back during the following lessons. 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /bitcoin_transfer/proof_of_ownership_as_an_authentication_method.md: -------------------------------------------------------------------------------- 1 | ## Proof of ownership as an authentication method {#proof-of-ownership-as-an-authentication-method} 2 | > [[2016.05.02](https://www.youtube.com/watch?v=dZNtbAFnr-0)] My name is Craig Wright and I am about to demonstrate a signing of a message with the public key that is associated with the first transaction ever done in Bitcoin. 3 | 4 | ```cs 5 | var bitcoinPrivateKey = new BitcoinSecret("XXXXXXXXXXXXXXXXXXXXXXXXXX"); 6 | 7 | var message = "I am Craig Wright"; 8 | string signature = bitcoinPrivateKey.PrivateKey.SignMessage(message); 9 | Console.WriteLine(signature); // IN5v9+3HGW1q71OqQ1boSZTm0/DCiMpI8E4JB1nD67TCbIVMRk/e3KrTT9GvOuu3NGN0w8R2lWOV2cxnBp+Of8c= 10 | ``` 11 | 12 | Was that so hard? 13 | 14 | You may remember Craig Wright, who really wanted us to believe he is Satoshi Nakamoto. 15 | He had successfully convinced a handful of influential Bitcoin people and journalists with some social engineering. 16 | Fortunately digital signatures do not work that way. 17 | Let's quickly find on the [Internet](https://en.bitcoin.it/wiki/Genesis_block) the first ever bitcoin address, associated with the genesis block: [1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa](https://blockchain.info/address/1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa) and verify his claim: 18 | 19 | ```cs 20 | var message = "I am Craig Wright"; 21 | var signature = "IN5v9+3HGW1q71OqQ1boSZTm0/DCiMpI8E4JB1nD67TCbIVMRk/e3KrTT9GvOuu3NGN0w8R2lWOV2cxnBp+Of8c="; 22 | 23 | var address = new BitcoinPubKeyAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"); 24 | bool isCraigWrightSatoshi = address.VerifyMessage(message, signature); 25 | 26 | Console.WriteLine("Is Craig Wright Satoshi? " + isCraigWrightSatoshi); 27 | ``` 28 | 29 | SPOILER ALERT! The bool will be false. 30 | 31 | Here is how you prove you are the owner of an address without moving coins: 32 | 33 | **Address:** 34 | [1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB](https://blockchain.info/address/1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB) 35 | **Message:** 36 | Nicolas Dorier Book Funding Address 37 | **Signature:** 38 | H1jiXPzun3rXi0N9v9R5fAWrfEae9WPmlL5DJBj1eTStSvpKdRR8Io6/uT9tGH/3OnzG6ym5yytuWoA9ahkC3dQ= 39 | 40 | This constitutes proof that Nicolas Dorier owns the private key of the book. 41 | **Exercise:** Verify that Nicolas sensei is not lying! 42 | 43 | ### Sidenote 44 | Do you know how PGP works? Pretty similar, right? 45 | Maybe this can be the foundation of a more user friendly PGP alternative. 46 | Please build it on top of NBitcoin:-) 47 | -------------------------------------------------------------------------------- /bitcoin_transfer/spend_your_coin.md: -------------------------------------------------------------------------------- 1 | ## Spend your coin {#spend-your-coin} 2 | 3 | So now that you know what a **stratis address**, a **ScriptPubKey**, a **private key**, and a **miner** are you will make your first **transaction** by hand. 4 | 5 | As you proceed through this lesson you will add code line by line as it is presented to build a method that will leave feedback for the book in a Twitter style message. 6 | 7 | Let’s start by looking at the **transaction** that contains the **TxOut** that you want to spend as we did previously: 8 | 9 | Create a new **Console Project** (>.net45) and install **QBitNinja.Client** NuGet. 10 | 11 | Have you already generated and noted a private key to yourself? Have you already get the corresponding sratis address and sent some funds there? If not, don't worry, I quickly reiterate how you can do it: 12 | 13 | ```cs 14 | var network = Network.Main; 15 | 16 | var privateKey = new Key(); 17 | var stratisPrivateKey = privateKey.GetWif(network); 18 | var address = stratisPrivateKey.GetAddress(); 19 | 20 | Console.WriteLine(bitcoinPrivateKey); 21 | Console.WriteLine(address); 22 | ``` 23 | 24 | Note the **stratisPrivateKey**, the **address**, send some coins there and note the transaction id (you can find it (probably) in your wallet software or with a blockexplorer, like [blockchain.info](http://blockchain.info/)). 25 | 26 | Import your private key: 27 | 28 | ```cs 29 | var stratisPrivateKey = new 30 | StratisSecret("cSZjE4aJNPpBtU6xvJ6J4iBzDgTmzTjbq8w2kqnYvAprBCyTsG4x"); 31 | var network = stratisPrivateKey.Network; 32 | var address = stratisPrivateKey.GetAddress(); 33 | 34 | Console.WriteLine(stratisPrivateKey); // cSZjE4aJNPpBtU6xvJ6J4iBzDgTmzTjbq8w2kqnYvAprBCyTsG4x 35 | Console.WriteLine(address); // mzK6Jy5mer3ABBxfHdcxXEChsn3mkv8qJv 36 | ``` 37 | 38 | And finally get the transaction info: 39 | ```cs 40 | var client = new QBitNinjaClient(network); 41 | var transactionId = uint256.Parse("e44587cf08b4f03b0e8b4ae7562217796ec47b8c91666681d71329b764add2e3"); 42 | var transactionResponse = client.GetTransaction(transactionId).Result; 43 | 44 | Console.WriteLine(transactionResponse.TransactionId); // e44587cf08b4f03b0e8b4ae7562217796ec47b8c91666681d71329b764add2e3 45 | Console.WriteLine(transactionResponse.Block.Confirmations); 46 | ``` 47 | 48 | Now we have all the information we need to creat our transactions. The main questions are: **from where, to where and how much?** 49 | 50 | ### From where? 51 | 52 | In our case, we want to spend the second outpoint. Here's how we have figured this out: 53 | ```cs 54 | var receivedCoins = transactionResponse.ReceivedCoins; 55 | OutPoint outPointToSpend = null; 56 | foreach (var coin in receivedCoins) 57 | { 58 | if (coin.TxOut.ScriptPubKey == stratisPrivateKey.ScriptPubKey) 59 | { 60 | outPointToSpend = coin.Outpoint; 61 | } 62 | } 63 | if(outPointToSpend == null) 64 | throw new Exception("TxOut doesn't contain our ScriptPubKey"); 65 | Console.WriteLine("We want to spend {0}. outpoint:", outPointToSpend.N + 1); 66 | ``` 67 | 68 | For the payment you will need to reference this outpoint in the transaction. You create a transaction as follows: 69 | 70 | ```cs 71 | var transaction = new Transaction(); 72 | transaction.Inputs.Add(new TxIn() 73 | { 74 | PrevOut = outPointToSpend 75 | }); 76 | ``` 77 | 78 | ### To where? 79 | 80 | Do you remember the main questions? **From where, to where and how much?** 81 | Constructing **TxIn** and adding to the transaction was the answer the "from where" question. 82 | Constructing **TxOut** and adding to the transaction is the answer for the remaining ones. 83 | 84 | The donation address for this book is: [1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB](https://blockchain.info/address/1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB) 85 | This money goes into my "Coffee and Sushi Wallet" that will keep me fed and compliant while writing the rest of the book. 86 | If you succeed to complete this challange you will be able to find your contribution among **Hall of the Makers** on http://n.stratis.ninja/ (ordered by generosity). 87 | ```cs 88 | var hallOfTheMakersAddress = new StratisPubKeyAddress("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB"); 89 | ``` 90 | If you are working on the testnet, send the testnet coins to any testnet address. 91 | ```cs 92 | var hallOfTheMakersAddress = StratisAddress.Create("mzp4No5cmCXjZUpf112B1XWsvWBfws5bbB"); 93 | ``` 94 | 95 | ### How much? 96 | If you want to send **0.5 Stratis** from a **transaction input** with **1 Stratis** you actually have to spend all! 97 | As the diagram shows below, your **transaction output** specifies **0.5** Stratis to Hall of The Makers and **0.4999** back to you. 98 | What happens to the remaining **0.0001 Stratis**? This is the miner fee in order to incentivize them to add this transaction into their next block. 99 | 100 | ![](../assets/SpendTx.png) 101 | 102 | ```cs 103 | TxOut hallOfTheMakersTxOut = new TxOut() 104 | { 105 | Value = new Money((decimal)0.5, MoneyUnit.Stratis), 106 | ScriptPubKey = hallOfTheMakersAddress.ScriptPubKey 107 | }; 108 | 109 | TxOut changeBackTxOut = new TxOut() 110 | { 111 | Value = new Money((decimal)0.4999, MoneyUnit.Stratis), 112 | ScriptPubKey = stratisPrivateKey.ScriptPubKey 113 | }; 114 | 115 | transaction.Outputs.Add(hallOfTheMakersTxOut); 116 | transaction.Outputs.Add(changeBackTxOut); 117 | ``` 118 | 119 | We can do some finetuning here. 120 | You can check the address with a blockexplorer I am working with on this whole chapter example (I am working on the testnet): http://tbtc.blockr.io/address/info/mzK6Jy5mer3ABBxfHdcxXEChsn3mkv8qJv 121 | 122 | ```cs 123 | // How much you want to TO 124 | var hallOfTheMakersAmount = new Money(0.5m, MoneyUnit.Stratis); 125 | /* At the time of writing the mining fee is 0.05usd 126 | * Depending on the market price and 127 | * On the currently advised mining fee, 128 | * You may consider to increase or decrease it 129 | */ 130 | var minerFee = new Money(0.0001m, MoneyUnit.Stratis); 131 | // How much you want to spend FROM 132 | var txInAmount = receivedCoins[(int) outPointToSpend.N].TxOut.Amount; 133 | Money changeBackAmount = txInAmount - hallOfTheMakersAmount - minerFee; 134 | ``` 135 | 136 | Let's add our calculated values to our TxOuts: 137 | ```cs 138 | TxOut hallOfTheMakersTxOut = new TxOut() 139 | { 140 | Value = hallOfTheMakersAmount, 141 | ScriptPubKey = hallOfTheMakersAddress.ScriptPubKey 142 | }; 143 | 144 | TxOut changeBackTxOut = new TxOut() 145 | { 146 | Value = changeBackAmount, 147 | ScriptPubKey = stratisPrivateKey.ScriptPubKey 148 | }; 149 | ``` 150 | 151 | And add them to our transaction: 152 | ```cs 153 | transaction.Outputs.Add(hallOfTheMakersTxOut); 154 | transaction.Outputs.Add(changeBackTxOut); 155 | ``` 156 | 157 | ### Message on The Blockchain 158 | 159 | Now add your feedback! This must be less than 40 bytes, or it will crash the application. 160 | This feedback, along with your transaction will appear (after transaction is confirmed) in the [Hall of The Makers](http://n.bitcoin.ninja/). 161 | 162 | ```cs 163 | var message = "nopara73 loves NStratis!"; 164 | var bytes = Encoding.UTF8.GetBytes(message); 165 | transaction.Outputs.Add(new TxOut() 166 | { 167 | Value = Money.Zero, 168 | ScriptPubKey = TxNullDataTemplate.Instance.GenerateScriptPubKey(bytes) 169 | }); 170 | ``` 171 | 172 | To sum up take a look at my whole transaction before signing: 173 | I have 3 **TxOut**, 2 with **value**, 1 without **value** (with the message). You can notice the differences between the **scriptPubKey**s of the "normal" **TxOut**s and the **scriptPubKey** of the **TxOut** with the message: 174 | 175 | ```json 176 | { 177 | "hash": "b7803df4b90fd615532bcbdb3b63eb1af5a2e4ae36f29a6fbf9f57d0a1842e0a", 178 | "ver": 1, 179 | "vin_sz": 1, 180 | "vout_sz": 3, 181 | "lock_time": 0, 182 | "size": 154, 183 | "in": [ 184 | { 185 | "prev_out": { 186 | "hash": "e44587cf08b4f03b0e8b4ae7562217796ec47b8c91666681d71329b764add2e3", 187 | "n": 1 188 | }, 189 | "scriptSig": "" 190 | } 191 | ], 192 | "out": [ 193 | { 194 | "value": "0.50000000", 195 | "scriptPubKey": "OP_DUP OP_HASH160 d3a689bc36464b9d74e1721fd321d4686eae594e OP_EQUALVERIFYOP_CHECKSIG" 196 | }, 197 | { 198 | "value": "0.62840112", 199 | "scriptPubKey": "OP_DUP OP_HASH160 ce2c16edb74aef1caa6db0078af9d3a5b8fd12d1 OP_EQUALVERIFYOP_CHECKSIG" 200 | }, 201 | { 202 | "value": "0.00000000", 203 | "scriptPubKey": "OP_RETURN 6e6f706172613733206c6f766573204e426974636f696e21" 204 | } 205 | ] 206 | } 207 | ``` 208 | 209 | Take a closer look at **TxIn**. We have **prev_out** and **scriptSig** there. 210 | **Exercise:** try to figure out what will be and how to get the **scriptSig** in our code before you read further! 211 | 212 | Let's check out the **hash** of **prev_out** in a blockexplorer: http://tbtc.blockr.io/tx/info/e44587cf08b4f03b0e8b4ae7562217796ec47b8c91666681d71329b764add2e3 213 | In **prev_out** **n** is 1. Since we are indexing from 0, this means I want to spend the second output of the transaction. 214 | In the blockexplorer we can see the corresponding address is ```mzK6Jy5mer3ABBxfHdcxXEChsn3mkv8qJv``` and I can get the scriptSig from the address like this: 215 | 216 | ```cs 217 | var address = BitcoinAddress.Create("mzK6Jy5mer3ABBxfHdcxXEChsn3mkv8qJv"); 218 | transaction.Inputs[0].ScriptSig = address.ScriptPubKey; 219 | ``` 220 | 221 | ### Sign your transaction 222 | 223 | Now that we have created the transaction, we must sign it. In other words, you will have to prove that you own the TxOut that you referenced in the input. 224 | 225 | Signing can be [complicated](https://en.stratis.it/w/images/en/7/70/Bitcoin_OpCheckSig_InDetail.png), but we’ll make it simple. 226 | 227 | First let's revisit the **scriptSig** of **in**, how we can get it from code. Remember, we copypasted the address above from a blockexplorer, now let's get it from our QBitNinja transactionResponse: 228 | 229 | ```cs 230 | transaction.Inputs[0].ScriptSig = stratisPrivateKey.ScriptPubKey; 231 | ``` 232 | 233 | Then you need to give your private key for signing: 234 | 235 | ```cs 236 | transaction.Sign(stratisPrivateKey, false); 237 | ``` 238 | 239 | ### Propagate your transactions 240 | Congratulations, you have signed your first transaction! Your transaction is ready to roll! All that is left is to propagate it to the network so the miners can see it. 241 | #### With QBitNinja: 242 | ```cs 243 | BroadcastResponse broadcastResponse = client.Broadcast(transaction).Result; 244 | 245 | if (!broadcastResponse.Success) 246 | { 247 | Console.WriteLine("ErrorCode: " + broadcastResponse.Error.ErrorCode); 248 | Console.WriteLine("Error message: " + broadcastResponse.Error.Reason); 249 | } 250 | else 251 | { 252 | Console.WriteLine("Success! You can check out the hash of the transaciton in any block explorer:"); 253 | Console.WriteLine(transaction.GetHash()); 254 | } 255 | ``` 256 | 257 | #### With your own Stratis Core: 258 | 259 | ```cs 260 | using (var node = Node.ConnectToLocal(network)) //Connect to the node 261 | { 262 | node.VersionHandshake(); //Say hello 263 | //Advertize your transaction (send just the hash) 264 | node.SendMessage(new InvPayload(InventoryType.MSG_TX, transaction.GetHash())); 265 | //Send it 266 | node.SendMessage(new TxPayload(transaction)); 267 | Thread.Sleep(500); //Wait a bit 268 | } 269 | ``` 270 | 271 | The **using** code block will take care of closing the connection to the node. That's it! 272 | 273 | You can also connect directly to the Stratis network, however I advise you to connect to your own trusted node (faster and easier) 274 | 275 | ## Need more practice? 276 | Youtube: [How to make your first transaction with NStratis](https://www.youtube.com/watch?v=X4ZwRWIF49w) 277 | CodeProject: [Create a Stratis transaction by hand.](http://www.codeproject.com/Articles/1151054/Create-a-Bitcoin-transaction-by-hand) 278 | CodeProject: [DotNetWallet - Build your own Stratis wallet in C#](https://www.codeproject.com/script/Articles/ArticleVersion.aspx?waid=214550&aid=1115639) 279 | -------------------------------------------------------------------------------- /bitcoin_transfer/the_blockchain_is_more_than_just_bitcoin.md: -------------------------------------------------------------------------------- 1 | ## “The Blockchain is more than just Bitcoin” {#the-blockchain-is-more-than-just-bitcoin} 2 | 3 | The interesting thing is that this same sentence is used by two different groups of people. 4 | It is used by Bitcoin-As-A-Currency believers as argument for their bullish prediction of Bitcoin’s value. 5 | It is also used by those who do not believe in the success of the currency, as an attempt to explain why Bitcoin has so much interest. 6 | 7 | But there is one thing we all agree on: an immutable database that cannot be censored, tampered with, or erased that is duplicated all around the world will have tremendous impact on other industries. 8 | 9 | Notaries who record facts that can be used in court could store their documents permanently in The Blockchain. Audits can become automatic and provable when assets and ownership are stored and transferred on The Blockchain. All Money Transmitters can prove their solvency publicly. Automatic trading scripts can trade between themselves without human intervention or authorization of a central authority. 10 | 11 | In the rest of this book we will explore the fundamentals required to enable all of these technologies and more. It all starts with spending a bitcoin. -------------------------------------------------------------------------------- /bitcoin_transfer/transaction.md: -------------------------------------------------------------------------------- 1 | ## Transaction {#transaction} 2 | 3 | > ([Mastering Stratis](https://github.com/bitcoinbook/bitcoinbook/)) Transactions are the most important part of the stratis system. Everything else in stratis are designed to ensure that transactions can be created, propagated on the network, validated, and finally added to the global ledger of transactions (the blockchain). Transactions are data structures that encode the transfer of value between participants in the stratis system. Each transaction is a public entry in Stratis blockchain, the global double-entry bookkeeping ledger. 4 | 5 | A transaction may have no recipient, or it may have several. **The same can be said for senders!** On the Blockchain, the sender and recipient are always abstracted with a ScriptPubKey, as we demonstrated in previous chapters. 6 | 7 | If you use Stratis Core your Transactions tab will show the transaction, like this: 8 | 9 | ![](../assets/StratisCoreTransaction.png) 10 | 11 | For now we are interested in the **Transaction ID**. In this case, it is ```f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94``` 12 | 13 | > **Note:** The TransactionId is defined by SHA256(SHA256(txbytes)) 14 | 15 | > **Note:** Do NOT use the TransactionId to handle unconfirmed transactions. The TransactionId can be manipulated before it is confirmed. This is known as “Transaction Malleability.” 16 | 17 | You can review the transaction on a blockexplorer like Blockchain.info: https://blockchain.info/tx/f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94 18 | But as a developer you will probably want a service that is easier to query and parse. 19 | As a C# developer and an NStratis user Nicolas Dorier's [QBit Ninja](http://docs.qbitninja.apiary.io/) will definitely be your best choice. It is an open source web service API to query the blockchain and for tracking wallets. 20 | QBit Ninja depends on [NStratis.Indexer](https://github.com/MetacoSA/NBitcoin.Indexer) which rely on Microsoft Azure Storage. C# developers are expected to use the [NuGet client package](http://www.nuget.org/packages/QBitninja.Client) instead of developping a wrapper around this API. 21 | 22 | If you go to http://api.qbit.ninja/transactions/f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94 you will see the raw bytes of your transaction. 23 | 24 | ![](../assets/RawTx.png) 25 | 26 | You can parse the transaction from hex with the following code: 27 | 28 | ```cs 29 | Transaction tx = new Transaction("0100000..."); 30 | ``` 31 | 32 | Quickly close the tab, before it scares you away, QBit Ninja queries the API and parses the information so go ahead and install **QBitNinja.Client** NuGet package. 33 | 34 | ![](../assets/QBitNuGet.png) 35 | 36 | Query the transaction by id: 37 | 38 | ```cs 39 | // Create a client 40 | QBitNinjaClient client = new QBitNinjaClient(Network.Main); 41 | // Parse transaction id to NStratis.uint256 so the client can eat it 42 | var transactionId = uint256.Parse("f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94"); 43 | // Query the transaction 44 | GetTransactionResponse transactionResponse = client.GetTransaction(transactionId).Result; 45 | ``` 46 | 47 | The type of **transactionResponse** is **GetTransactionResponse**. It lives under QBitNinja.Client.Models namespace. You can get **NStratis.Transaction** type from it: 48 | 49 | ```cs 50 | NStratis.Transaction transaction = transactionResponse.Transaction; 51 | ``` 52 | 53 | Let's see an example getting back the transaction id with both classes: 54 | 55 | ```cs 56 | Console.WriteLine(transactionResponse.TransactionId); // f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94 57 | Console.WriteLine(transaction.GetHash()); // f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94 58 | ``` 59 | 60 | **GetTransactionResponse** has additional information about the transaction like the value and scriptPubKey of the inputs being spent in the transaction. 61 | 62 | The relevant parts for now are the **inputs** and **outputs**. You can see that out 13.19683492 Stratis has been sent to a ScriptPubKey: 63 | 64 | ```cs 65 | List receivedCoins = transactionResponse.ReceivedCoins; 66 | foreach (var coin in receivedCoins) 67 | { 68 | Money amount = (Money) coin.Amount; 69 | 70 | Console.WriteLine(amount.ToDecimal(MoneyUnit.BTC)); 71 | var paymentScript = coin.TxOut.ScriptPubKey; 72 | Console.WriteLine(paymentScript); // It's the ScriptPubKey 73 | var address = paymentScript.GetDestinationAddress(Network.Main); 74 | Console.WriteLine(address); 75 | Console.WriteLine(); 76 | } 77 | ``` 78 | 79 | We have written some information about the RECEIVED COINS using QBitNinja's GetTransactionResponse class. 80 | **Exercise**: Write the same information about the SPENT COINS using QBitNinja's GetTransactionResponse class! 81 | 82 | Let's see how we can get the same information about the RECEIVED COINS using NStratis Transaction class. 83 | 84 | ```cs 85 | var outputs = transaction.Outputs; 86 | foreach (TxOut output in outputs) 87 | { 88 | Money amount = output.Value; 89 | 90 | Console.WriteLine(amount.ToDecimal(MoneyUnit.Stratis)); 91 | var paymentScript = output.ScriptPubKey; 92 | Console.WriteLine(paymentScript); // It's the ScriptPubKey 93 | var address = paymentScript.GetDestinationAddress(Network.Main); 94 | Console.WriteLine(address); 95 | Console.WriteLine(); 96 | } 97 | ``` 98 | 99 | Now let's examine the **inputs**. If you look at them you will notice a previous output is referenced. Each input shows you which previous out has been spent in order to fund this transaction. 100 | 101 | ```cs 102 | var inputs = transaction.Inputs; 103 | foreach (TxIn input in inputs) 104 | { 105 | OutPoint previousOutpoint = input.PrevOut; 106 | Console.WriteLine(previousOutpoint.Hash); // hash of prev tx 107 | Console.WriteLine(previousOutpoint.N); // idx of out from prev tx, that has been spent in the current tx 108 | Console.WriteLine(); 109 | } 110 | ``` 111 | 112 | The terms **TxOut**, **Output** and **out** are synonymous. 113 | Not to be confused with **OutPoint**, but more on this later. 114 | 115 | In summary, the TxOut represents an amount of stratis and a **ScriptPubKey**. (Recipient) 116 | 117 | ![](../assets/TxOut.png) 118 | As illustration let's create a txout with 21 stratis from the first ScriptPubKey in our current transaction: 119 | 120 | ```cs 121 | Money twentyOneBtc = new Money(21, MoneyUnit.BTC); 122 | var scriptPubKey = transaction.Outputs.First().ScriptPubKey; 123 | TxOut txOut = new TxOut(twentyOneBtc, scriptPubKey); 124 | ``` 125 | 126 | Every **TxOut** is uniquely addressed at the blockchain level by the ID of the transaction which include it and its index inside it. We call such reference an **Outpoint**. 127 | 128 | ![](../assets/OutPoint.png) 129 | 130 | For example, the **Outpoint** of the **TxOut** with 13.19683492 Stratis in our transaction is (4788c5ef8ffd0463422bcafdfab240f5bf0be690482ceccde79c51cfce209edd, 0). 131 | 132 | ```cs 133 | OutPoint firstOutPoint = spentCoins.First().Outpoint; 134 | Console.WriteLine(firstOutPoint.Hash); // 4788c5ef8ffd0463422bcafdfab240f5bf0be690482ceccde79c51cfce209edd 135 | Console.WriteLine(firstOutPoint.N); // 0 136 | ``` 137 | 138 | Now let’s take a closer look at the inputs (aka **TxIn**) of the transaction: 139 | 140 | ![](../assets/TxIn.png) 141 | 142 | The **TxIn** is composed of the **Outpoint** of the **TxOut** being spent and of the **ScriptSig** ( we can see the ScriptSig as the “Proof of Ownership”) In our transaction there are actually 9 inputs. 143 | 144 | ```cs 145 | Console.WriteLine(transaction.Inputs.Count); // 9 146 | ``` 147 | 148 | With the previous outpoint's transaction ID we can review the information associated with that transaction. 149 | ```cs 150 | OutPoint firstPreviousOutPoint = transaction.Inputs.First().PrevOut; 151 | var firstPreviousTransaction = client.GetTransaction(firstPreviousOutPoint.Hash).Result.Transaction; 152 | Console.WriteLine(firstPreviousTransaction.IsCoinBase); // False 153 | ``` 154 | 155 | We could continue to trace the transaction IDs back in this manner until we reach a **coinbase transaction**, the transaction including the newly mined coin by a miner. 156 | **Exercise:** Follow the first input of this transaction and its ancestors until you find a coinbase transaction! 157 | Hint: After a few minutes and 30-40 transaction, I gave up tracing back. 158 | Yes, you've guessed right, it is not the most efficient way to do this, but a good exercise. 159 | 160 | In our example, the outputs were for a total of 13.19**70**3492 Strtis. 161 | 162 | ```cs 163 | Money spentAmount = Money.Zero; 164 | foreach (var spentCoin in spentCoins) 165 | { 166 | spentAmount = (Money)spentCoin.Amount.Add(spentAmount); 167 | } 168 | Console.WriteLine(spentAmount.ToDecimal(MoneyUnit.BTC)); // 13.19703492 169 | ``` 170 | 171 | In this transaction 13.19**68**3492 Stratis were received. 172 | 173 | **Exercise:** Get the total received amount, as I have been doing with the spent amount. 174 | 175 | That means 0.0002 Stratis (or 13.19**70**3492 - 13.19**68**3492) is not accounted for! The difference between the inputs and outputs are called **Transaction Fees** or **Miner’s Fees**. This is the money that the miner collects for including a given transaction in a block. 176 | 177 | ```cs 178 | var fee = transaction.GetFee(spentCoins.ToArray()); 179 | Console.WriteLine(fee); 180 | ``` 181 | 182 | You should note that a **coinbase transaction** is the only transaction whose value of output are superior to the value of input. This effectively correspond to coin creation. So by definition there is no fee in a coinbase transaction. The coinbase transaction is the first transaction of every block. 183 | The consensus rule enforce that the sum of output's value in the coinbase transaction does not exceed the sum of transaction fees in the block plus the mining reward. 184 | -------------------------------------------------------------------------------- /cover.md: -------------------------------------------------------------------------------- 1 | 2 | ![](assets/bitcoin.png) 3 | 4 | # Programming The Blockchain in C**\#** 5 | _Authored by Nicolas Dorier 6 | Creator of NStratis, The .NET Stratis 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 {#foreword} 2 | 3 | An extract in _Fountain Head_ by Ayn Rand resonated with me. 4 | 5 | 6 | > Gail Wynand, the powerful puppet master of the world, and Howard Roark, the protagonist building architect discussed together. Gail finds a strange relief when he is with Roark, not knowing where it comes from, he questions him. 7 | > Wynand asked: 8 | > "Howard, have you ever been in love?" 9 | > Roark turned to look straight at him and answer quietly: 10 | > "I still am." 11 | > "But when you walk through a building, what you feel is greater than that?" 12 | > "Much greater, Gail" 13 | > "I was thinking of people who say that happiness is impossible on earth. Look how hard they all try to find some joy in life. Look how they struggle for it. Why should any living creature exist in pain? By what conceivable right can anyone demand that a human being exist for anything but his own joy? Every one of them wants it. Every part of him wants it. But they never find it. I wonder why. They whine and say they don't understand the meaning of life. There's a particular kind of people that I despise. Those who seek some sort of a higher purpose or 'universal goal,' who don't know what to live for, who moan that they must ‘find themselves.’ You hear it all around us. That seems to be the official bromide of our century. Every book you open. Every drooling self-confession. It seems to be the noble thing to confess. I'd think it would be the most shameful one." 14 | > "Look, Gail". Roark got up, reached out, tore a thick branch off a tree, held it in both hands, one fist closed at each end; then, his wrists and knuckles tensed against the resistance, he bent the branch slowly into an arc. "Now I can make what I want of it: a bow, a spear, a cane, a railing. That's the meaning of life." 15 | > "Your strength?" 16 | > "Your work." He tossed the branch aside. "The material the earth offers you and what you make of it..." 17 | 18 | I think The Blockchain is like the tree branch. For outsiders, it feels like a boring and useless collection of bits. For programmers and entrepreneurs, it is a marvelous raw material that can be shaped with our imagination. We give it meaning and purpose. 19 | 20 | Just as you need to know about wood to make a bow, spear or cane from a branch, you need to learn about programming to shape the Blockchain. My hope is that you will discover how much your skill and intelligence can shape that useless collection of bits. 21 | 22 | Let me warn you: learning about Bitcoin is like taking the red pill from _The Matrix._ You may find yourself ready to quit your job to work on it full time. 23 | 24 | This book will take you from basic to advanced use of the Blockchain. It will not teach you how to use an API (such as the RPC API provided with Bitcoin Core), but it will teach you how to make such an API. 25 | 26 | > Satoshi Nakamoto once described Bitcoin as “boring grey in colour.” 27 | 28 | While programming to an API can assist in getting an application up quickly, the developer is limited to innovations that can take place against the API. By fully understanding the Blockchain, the developer is empowered to unleash its full potential. -------------------------------------------------------------------------------- /implementations/README.md: -------------------------------------------------------------------------------- 1 | # Case studies {#implementations} 2 | 3 | In this chapter you will see how existing implementations are made on top of NStratis. 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 | # HiddenBitcoin: Managing keys (HD wallet) {#hiddenbitcoin-keystorage} 2 | 3 | ([nopara73](https://github.com/nopara73)) I am developing a privacy oriented Bitcoin wallet, called [HiddenWallet](https://github.com/nopara73/HiddenWallet). The [HiddenBitcoin](https://github.com/nopara73/HiddenBitcoin) library is the introduction of an other abstraction layer between NBitcoin and the user interface. 4 | 5 | A Bitcoin wallet have three key functions and this case study will be structured around them: 6 | 7 | 1. Securely stores keys and manages the access to them. 8 | 2. Monitors these keys, and other keys on The Blockchain. 9 | 3. Builds transactions and submits them. 10 | 11 | In this lesson I am going to tackle the key storage function. 12 | If you want to examine the code more extensively you can find the solution on [GitHub](https://github.com/nopara73/HiddenBitcoin). 13 | If you just want to know how to quickly set it up and use it you can find my high level tutorial on [CodeProject](http://www.codeproject.com/Articles/1096320/HiddenBitcoin-High-level-Csharp-Bitcoin-wallet-lib). 14 | 15 | **How high level is it?** In my opinion a GUI developer, designer should not be able to make too much mistakes. They should not know about inputs and outputs and scriptpubkeys. They should stick at the addresses, privatekeys and wallets level. Also NBitcoin should be fully abstracted away. 16 | 17 | ## Key storage design decisions 18 | 19 | Now it is a great time to give you a template on what decisions have to be make for storing the keys and what to keep in mind while making them. 20 | 21 | ### Using only one key 22 | 23 | This is a shortcut. There are not too many situations I can come up with where going down this road can be justified. Yet it is not impossible it will be the most suitable for your needs. 24 | As a bad example here is an illustration for a Bitcoin wallet I have built, what only uses one key. I leave it to you to think of the consequences. 25 | 26 | ![](../assets/TransparentWallet2.png) 27 | 28 | ### JBOK wallets 29 | 30 | It stands for **J**ust a **B**unch **O**f **K**eys. At the time of writing the reference client uses this method to store keys. 31 | The problem with this the user has to periodically backup his wallet. Yet if you want to be able importing or dropping keys, changing password you need to use this or some kind of hybrid combination of this and a deterministic wallet. I decided not to use this since my HiddenWallet is trying to innovate towards privacy and I can have a more sound wallet structure without it. 32 | 33 | ### BIP38 (Part 2) - Untrusted third party key generator 34 | Just to reiterate: the idea is to generate a PassphraseCode to the key generator. With this PassphraseCode, he will be able to generate encrypted keys on your behalf, without knowing your password, nor any private key. 35 | HiddenWallet is a desktop wallet (and probably it is not going to change for a while). Thus I do not need to use an untrusted third party for key generation and key storage purposes. I decided not to implement it just yet. 36 | 37 | ### SHD wallet 38 | 39 | This is the wallet structure I have implemented. Ok, you got me, I just came up with this word. It does not exist and nobody uses it. But in my mind it stands for **S**tealth and **H**ierarchical **D**eterministic wallet. It is the best way to describe what I built. 40 | Before I get into the code I would like to note I have only implemented the Stealth part of it, becuase it was a low hanging fruit. I am not sure stealth addresses will have any use in the future of Bitcoin. 41 | 42 | A stealth address looks like this: ```waPXAvDCDGv8sXYRY6XDEymDGscYeepXBV5tgSDF1JHn61rzNk4EXTuBfx22J2W9rPAszXFmPXwD2m52psYhXQe5Yu1cG26A7hkPxs``` 43 | 44 | ## Black box 45 | I implemented a class, called it **Safe**. Using this class, as a black box is intuitive. 46 | 47 | ```cs 48 | var network = Network.MainNet; 49 | ``` 50 | 51 | The **Network** is not **NBitcoin.Network**, since the GUI developer should not know it is using NBitcoin. Also you have more network options to choose from in NBitcoin, but HiddenBitcoin is cannot handle all of them. At the moment it supports ```MainNet``` and ```TestNet```. 52 | The Network is an enum, it can be found under **HiddenBitcoin.DataClasses** namespace. 53 | 54 | ```cs 55 | string mnemonic; 56 | Safe safe = Safe.Create(out mnemonic, "password", walletFilePath: @"Wallets\hiddenWallet.hid", network); 57 | Console.WriteLine(mnemonic); 58 | ``` 59 | 60 | You can also load or recover the safe: 61 | 62 | ```cs 63 | Safe loadedSafe = Safe.Load("password", walletFilePath: @"Wallets\hiddenWallet.hid"); 64 | if (network != loadedSafe.Network) 65 | throw new Exception("WrongNetwork"); 66 | 67 | Safe recoveredSafe = Safe.Recover(mnemonic, "password", walletFilePath: @"Wallets\sameHiddenWallet.hid", network); 68 | ``` 69 | 70 | You can also get some keys out of the safe as strings: 71 | 72 | ```cs 73 | Console.WriteLine("Seed private key: " + safe.Seed); 74 | Console.WriteLine("Seed public key: " + safe.SeedPublicKey); 75 | Console.WriteLine("Third child address: " + safe.GetAddress(2)); 76 | Console.WriteLine("First child private key: " + safe.GetPrivateKey(0)); 77 | Console.WriteLine("Second child private key and the corresponding address: "); 78 | Console.WriteLine(safe.GetPrivateKeyAddressPair(1).PrivateKey); 79 | Console.WriteLine(safe.GetPrivateKeyAddressPair(1).Address); 80 | Console.WriteLine("The stealth address: " + safe.StealthAddress); 81 | Console.WriteLine("Scan and spend private keys for stealth payments:"); 82 | Console.WriteLine(loadedSafe.ScanPrivateKey); 83 | Console.WriteLine(loadedSafe.SpendPrivateKey); 84 | ``` 85 | 86 | ``` 87 | Seed private key: xprv9s21ZrQH143K4RBm26TMm3qwTtR3Eyh22xDEN3TBebgfAvHPPSjxxFnFGDtnNHvqZ7pihGmAc8o9y1UvfEzcxSzyXAnmvTBowCNi69nXsqJ 88 | Seed public key: xpub661MyMwAqRbcGuGE87zN8Bng1vFXeSQsQB8qARroCwDe3icXvz4DW46j7U6fX8NsKhqcxR7K1mDX4gTbtvCGdeJz5M7py3yEqMsjUH2DYhb 89 | Third child address: 17pGpPX1A2sCdqJXsC5BiwdFphFVgJR9nk 90 | First child private key: xprv9ubnoo3dgCYfrWbYBEM71WoBvzwTtQemEdjW836CeWJYunYBskQhq3nrJMvNBCCFpnU5GbgbL1b2QbPHA4rRPESEhqfKzae5oWe7SAMuxAV 91 | Second child private key and the corresponding address: 92 | xprv9ubnoo3dgCYfuE1hVB3F3Sh5YFJUNUjyZ68PDzPNhpmtqWDtD45zucZYMUAjY22HNxaY6tsvGAdJdcyALCMm2mTAvA4pEp1m7y3BSccKY4r 93 | 19FHdsj2YT79TuxbWcDMz9opTU28L1memr 94 | The stealth address: vJmuFuLggpgzivm3UUjQguLhMA6C1SnYFJu5N6QkmXYRCU3nG1Ww36VcXy6zXpJvGeVTidxcsu7U19sfB1rxHhzvSNV5eGGLk6G1Cb 95 | Scan and spend private keys for stealth payments: 96 | L5CTS4U27umRfSBu2ztxsyUeMEYzJJk3HvCp3deSQBJWmRSUqCLg 97 | KyXveppF4Xm3KwJgG7EBSi6SxfMTkaDXYYmv7c7xWRcF7yUNpswp 98 | ``` 99 | 100 | **Note:** Ideally the seed keys are never used. It is a better practice if you start iterating through the keys with the getters of the safe. 101 | 102 | ## White box 103 | 104 | ### Safe.Create 105 | 106 | ```cs 107 | // Creates a mnemonic, a seed, encrypts it and stores in the specified path. 108 | public static Safe Create(out string mnemonic, string password, string walletFilePath, Network network) 109 | { 110 | var safe = new Safe(password, walletFilePath, network); 111 | mnemonic = safe.SetSeed(password).ToString(); 112 | safe.Save(password, walletFilePath, network); 113 | 114 | return safe; 115 | } 116 | ``` 117 | 118 | ```safe.SetSeed``` creates a mnemonic and set the ```_seedPrivateKey```. Finally it returns the mnemonic, so we can give it back to the user of the class. 119 | 120 | ![](../assets/RootKey.png) 121 | 122 | ```cs 123 | private ExtKey _seedPrivateKey; 124 | private Mnemonic SetSeed(string password) 125 | { 126 | var mnemonic = new Mnemonic(Wordlist.English, WordCount.Twelve); 127 | 128 | _seedPrivateKey = mnemonic.DeriveExtKey(password); 129 | 130 | return mnemonic; 131 | } 132 | ``` 133 | 134 | ### safe.Save 135 | Saves a wallet file, the question is what do we have inside it? 136 | 137 | ```json 138 | { 139 | "EncryptedSeed":"6PYXR8U5Nu9UoGZcU95DWWKCXppKnYBUKyJgze6DX6bQDNwFzNdJApUzXT", 140 | "ChainCode":"C+2MiZU7R/33bkvgdDqdQp7xx3nXHSIzS6bUgRsnaus=", 141 | "Network":"MainNet" 142 | } 143 | ``` 144 | 145 | The wallet file is in JSON format. 146 | We can get the chain code and private key from an ExtKey. It works the other way around too. 147 | 148 | ```cs 149 | Key privateKey = _seedPrivateKey.PrivateKey; 150 | byte[] chainCode = _seedPrivateKey.ChainCode; 151 | ``` 152 | 153 | Finally we encrypt the private key. 154 | 155 | ![](../assets/EncryptedKey.png) 156 | 157 | ```cs 158 | string encryptedBitcoinPrivateKeyString = privateKey.GetEncryptedBitcoinSecret(password, _network).ToWif(); 159 | string chainCodeString = Convert.ToBase64String(chainCode); 160 | string networkString = network.ToString(); 161 | ``` 162 | 163 | ### Safe.Load 164 | 165 | Let's reverse the save process. 166 | 167 | ```cs 168 | public static Safe Load(string password, string walletFilePath) 169 | { 170 | if (!File.Exists(walletFilePath)) 171 | throw new Exception("WalletFileDoesNotExists"); 172 | 173 | var walletFileRawContent = WalletFileSerializer.Deserialize(walletFilePath); 174 | 175 | var encryptedBitcoinPrivateKeyString = walletFileRawContent.EncryptedSeed; 176 | var chainCodeString = walletFileRawContent.ChainCode; 177 | 178 | var chainCode = Convert.FromBase64String(chainCodeString); 179 | 180 | Network network; 181 | var networkString = walletFileRawContent.Network; 182 | if (networkString == Network.MainNet.ToString()) 183 | network = Network.MainNet; 184 | else if (networkString == Network.TestNet.ToString()) 185 | network = Network.TestNet; 186 | else throw new Exception("NotRecognizedNetworkInWalletFile"); 187 | 188 | var safe = new Safe(password, walletFilePath, network); 189 | 190 | var privateKey = Key.Parse(encryptedBitcoinPrivateKeyString, password, safe._network); 191 | var seedExtKey = new ExtKey(privateKey, chainCode); 192 | safe._seedPrivateKey = seedExtKey; 193 | 194 | return safe; 195 | } 196 | ``` 197 | 198 | Here is what happens in the Safe constructor: 199 | 200 | ```cs 201 | private Safe(string password, string walletFilePath, Network network) 202 | { 203 | SetNetwork(network); 204 | 205 | SetSeed(password, mnemonicString); 206 | 207 | WalletFilePath = walletFilePath; 208 | } 209 | ``` 210 | 211 | ### SetNetwork 212 | Inside the class we like to work with ```NBitcoin.Network```. So let's set a private member for that. 213 | 214 | ```cs 215 | private NBitcoin.Network _network; 216 | private void SetNetwork(Network network) 217 | { 218 | if (network == Network.MainNet) 219 | _network = NBitcoin.Network.Main; 220 | else if (network == Network.TestNet) 221 | _network = NBitcoin.Network.TestNet; 222 | else throw new Exception("WrongNetwork"); 223 | } 224 | ``` 225 | 226 | ### Safe.Recover 227 | 228 | ```cs 229 | public static Safe Recover(string mnemonic, string password, string walletFilePath, Network network) 230 | { 231 | var safe = new Safe(password, walletFilePath, network, mnemonic); 232 | safe.Save(password, walletFilePath, network); 233 | return safe; 234 | } 235 | ``` 236 | 237 | For this to work we have to expand the constructor: 238 | 239 | ```cs 240 | private Safe(string password, string walletFilePath, Network network, string mnemonicString = null) 241 | { 242 | SetNetwork(network); 243 | 244 | if (mnemonicString != null) 245 | { 246 | var mnemonic = new Mnemonic(mnemonicString); 247 | _seedPrivateKey = mnemonic.DeriveExtKey(password); 248 | } 249 | 250 | WalletFilePath = walletFilePath; 251 | } 252 | ``` 253 | 254 | ### Getters 255 | 256 | Here is how I derive the keys. For my purposes it doesn't make too much sense to use some complicated keypath: 257 | 258 | ```cs 259 | public PrivateKeyAddressPair GetPrivateKeyAddressPair(int index) 260 | { 261 | var foo = _seedPrivateKey.Derive(index, true).GetWif(_network); 262 | return new PrivateKeyAddressPair 263 | { 264 | PrivateKey = foo.ToWif(), 265 | Address = foo.ScriptPubKey.GetDestinationAddress(_network).ToWif() 266 | }; 267 | } 268 | ``` 269 | 270 | ### Stealth 271 | 272 | ```cs 273 | private Key _spendPrivateKey => _seedPrivateKey.PrivateKey; 274 | public string SpendPrivateKey => _spendPrivateKey.GetWif(_network).ToWif(); 275 | private Key _scanPrivateKey => _seedPrivateKey.Derive(0, hardened: true).PrivateKey; 276 | public string ScanPrivateKey => _scanPrivateKey.GetWif(_network).ToWif(); 277 | 278 | public string StealthAddress => new BitcoinStealthAddress 279 | (_scanPrivateKey.PubKey, new[] {_spendPrivateKey.PubKey}, 1, null, _network 280 | ).ToWif(); 281 | ``` 282 | 283 | 284 | -------------------------------------------------------------------------------- /introduction/README.md: -------------------------------------------------------------------------------- 1 | # Introduction {#introduction} -------------------------------------------------------------------------------- /introduction/complementary_reading.md: -------------------------------------------------------------------------------- 1 | ## Complementary Reading {#complementary-reading} 2 | 3 | Here is some literature that you can use to complete this book: 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) -------------------------------------------------------------------------------- /introduction/crowdfunding_this_book.md: -------------------------------------------------------------------------------- 1 | ## Crowdfunding this book {#crowdfunding-this-book} 2 | 3 | If we want to continue to make great stuff for you we need to buy pizza, sushi and coffee. It is our responsibility to get enough coins for that. Also, we are too lazy to keep writing a whole book without hearing your feedback. 4 | **Bitcoin address:** [1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB](https://blockchain.info/address/1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB) 5 | 6 | As cryptocurrency addicts might say: Proof of Stake and Proof of Work are the best expression of affection, everything else is Fiat. 7 | 8 | Find out more about our work at http://n.bitcoin.ninja/ -------------------------------------------------------------------------------- /introduction/diagrams.md: -------------------------------------------------------------------------------- 1 | ## Diagrams {#diagrams} 2 | 3 | Most of the diagrams will have the same shape, they must be read by interpreting inward arrows like components to create the target: 4 | 5 | For example, the following diagram should be read as 6 | ```Key + Password = EncryptedKey``` 7 | ```EncryptedKey + Password = Key``` 8 | 9 | ![](../assets/encrypted_key.png) 10 | 11 | Code is nice, but sometimes a picture worths a thousand words. (Don’t worry, we’ll also write the code.) -------------------------------------------------------------------------------- /introduction/license_cc_asa_3u.md: -------------------------------------------------------------------------------- 1 | ## License: CC (ASA 3U) {#license-cc-asa-3u} 2 | 3 | You are free to share and adapt, as specified in the Attribution-Share Alike 3.0 Unported (CC BY-SA 3.0). 4 | 5 | ![](../assets/ccasa3u.png) -------------------------------------------------------------------------------- /introduction/pre-requisites.md: -------------------------------------------------------------------------------- 1 | ## Pre-requisites {#pre-requisites} 2 | 3 | ### Skills {#skills} 4 | 5 | * You need to be comfortable with object oriented as well as functional programming. 6 | * A basic grasp of C# is helpful, but we feel the code will be legible to Java and other C-based languages. 7 | * No mathematic knowledge is required. We will not cover cryptography beyond the bare minimum that you need to know to make a secure service. 8 | * You don’t need to have deep knowledge of Stratis. 9 | 10 | ### Tools {#tools} 11 | 12 | * [Visual Studio Community Edition](https://www.visualstudio.com/) on Windows or [Xamarin Studio](https://store.xamarin.com) on Mac and Linux. (Both free) 13 | * [Stratis Core](https://stratis.org/en/stratis-core/) - Ideally you have it, but you can just proceed without it. 14 | 15 | > **Tip:** If disk-space is an issue, consider running Stratis Core in pruning mode. It is practically the same as a full node (including security), except it throws away some of the old history. 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /introduction/project_setup.md: -------------------------------------------------------------------------------- 1 | ## Project Setup {#project-setup} 2 | 3 | Before we begin with the instruction, we should describe how we expect your projects to be set up. 4 | 5 | 1. Create a new Project in Visual Studio (.NET 4.5 or higher) 6 | 2. Right click on “References” in Solution Explorer and select “Manage NuGet Packages…” 7 | 3. Search for “**NStratis”** and install it. (Or NStratis.Mono on MAC and Linux.) 8 | ![](../assets/nuget.png) 9 | 10 | > **Tip:** If you are on MAC or Linux and reference NStratis instead of NBitcoin.Mono you will be missing some classes. 11 | 12 | NStratis is the .NET Stratis library, it is open-source, maintained by Nicolas Dorier, the main author of this book. 13 | This library should always be included if you do anything Stratis related in C#. 14 | NStratis supports cross-platform applications. 15 | 16 | ### ## # How to debug into NStratis source code (optional) 17 | 18 | NStratis lets you debug into its code, to make your life easier. For this feature to work make sure you have source server support enabled in Visual Studio (Tools/Options). 19 | ![](../assets/visualstudio_enablesourceserversupport.png) 20 | 21 | Now, if you step into NStratis code, the source code will be automatically fetched on github, and appear in visual studio debugger. 22 | -------------------------------------------------------------------------------- /introduction/why_blockchain_programming_and_not_bitcoin_program.md: -------------------------------------------------------------------------------- 1 | ## Why Blockchain Programming and not Stratis Programming? {#why-blockchain-programming-and-not-Stratis-programming} 2 | 3 | The Blockchain is to gold what Stratis is to jewelry. 4 | 5 | We did not compare Stratis to a gold coin, but rather with a jewelry. That’s because gold’s first killer app was jewelry. Coins came later. 6 | 7 | Do not be fooled into thinking that Stratis is flawed while the Blockchain is valuable. If gold is valuable, would you throw away a gold necklace? The Blockchain is built on and thrives because of Stratis. Any increase in value of the Blockchain will increase the amount of Stratis that is spent to use it, which will increase its demand. 8 | 9 | Whether or not your app will use the “Stratis as a currency” feature is your own decision. 10 | 11 | Blockchain is the raw material. Stratis is the fuel. Stratis as a currency is a feature that emerges every time someone thinks this fuel is also a good medium of exchange. You can do a lot more with the Blockchain than exchange value. You don’t even have to believe in the currency. We will show you how to use Stratis as a currency in this book, but that’s not all! 12 | -------------------------------------------------------------------------------- /introduction/why_c.md: -------------------------------------------------------------------------------- 1 | ## Why C#? {#why-c} 2 | 3 | The .NET framework is popular in corporate environments. We also believe this is the perfect tool for startups and hobbyists. 4 | 5 | * You can create portable code that functions across iOS, Android, Windows tablets/phones, desktops, servers and embedded devices, for free. 6 | * Everything from the compiler to the core runtime is open source. 7 | * The BizSpark program allows any startup to get all Microsoft tools, including $150/month of Azure service, for free. 8 | * Visual Studio Community 2015 is a professional grade IDE that you can use freely as hobbyist. 9 | * C# is closely related to Java and C++. As such, it can be easily read by a big base of developers. 10 | * Nicolas Dorier, one of the authors of this book, created the most popular Bitcoin Framework for .NET, called [NStratis](https://github.com/MetacoSA/NStratis). 11 | * Every person I met who learned about C# will tell you it is the best language out there, even if it is not the one they are using at the moment. 12 | 13 | The authors of this book have over 15 years combined experience with C#. It is our go-to language for any project for fun or profit. 14 | 15 | > **Fact:** We have not been paid by Microsoft. It’s not too late to change that. 16 | 17 | -------------------------------------------------------------------------------- /introduction/why_do_people_hate_bitcoin.md: -------------------------------------------------------------------------------- 1 | ## Why this book?{#why-do-people-hate-new-technologies-stratis} 2 | 3 | Understanding Stratis is quite a challenge. You might be completely unfamiliar with it. You might be heavily invested, following the news for years, already became completely addicted, but still the whole thing feels like a big mess. Or you feel like you understand it, but you are lacking of practical knowledge. If you fell into any of the these categories, we believe this book is the best investment for your time. 4 | 5 | If you let us guide you through the world of blockchain. We will not only armor you with the skills who are necessary to win any [/r/Stratis](http://www.reddit.com/r/Stratis/) arguments, but also enable you to wisely choose among the countless developer opportunities that come in your way daily. Furthermore you will also be able to make those ideas reality. And in general, what better way is there to understand something, but to actually code it? 6 | -------------------------------------------------------------------------------- /key_generation/key_generation.md: -------------------------------------------------------------------------------- 1 | # Key generation and encryption {#key-generation-encryption} 2 | 3 | ## Is it random enough? {#is-it-random-enough} 4 | 5 | When you call **new Key()**, under the hood, you are using a PRNG (Pseudo-Random-Number-Generator) to generate your private key. On windows, it uses the **RNGCryptoServiceProvider**, a .NET wrapper around the Windows Crypto API. 6 | 7 | On Android, I use the **SecureRandom**, and in fact, you can use your own implementation with **RandomUtils.Random**. 8 | 9 | On IOS, I have not implemented it and you need to create your **IRandom** implementation. 10 | 11 | For a computer, being random is hard. But the biggest issue is that it is impossible to know if a series of numbers is really random. 12 | 13 | If malware modifies your PRNG (and so, can predict the numbers you will generate), you won’t see it until it is too late. 14 | 15 | It means that a cross platform and naïve implementation of PRNG (like using the computer’s clock combined with CPU speed) is dangerous. But you won’t see it until it is too late. 16 | 17 | For performance reasons, most PRNG works the same way: a random number, called **Seed**, is chosen, then a predictable formula generates the next numbers each time you ask for it. 18 | 19 | The amount of randomness of the seed is defined by a measure we call **Entropy**, but the amount of **Entropy** also depends on the observer. 20 | 21 | Let’s say you generate a seed from your clock time. 22 | And let’s imagine that your clock has 1ms of resolution. (Reality is more ~15ms.) 23 | 24 | If your attacker knows that you generated the key last week, then your seed has 25 | 1000 \* 60 \* 60 \* 24 \* 7 = 604800000 possibilities. 26 | 27 | For such attacker, the entropy is LOG(604800000;2) = 29.17 bits. 28 | 29 | And enumerating such number on my home computer took less than 2 seconds. We call such enumeration “brute forcing”. 30 | 31 | However let’s say, you use the clock’s time + the process id for generating the seed. 32 | Let’s imagine that there are 1024 different process ids. 33 | 34 | So now, the attacker needs to enumerate 604800000 \* 1024 possibilities, which take around 2000 seconds. 35 | Now, let’s add the time when I turned on my computer, assuming the attacker knows I turned it on today, it adds 86400000 possibilities. 36 | 37 | Now the attacker needs to enumerate 604800000 \* 1024 \* 86400000 = 5,35088E+19 possibilities. 38 | However, keep in mind that if the attacker infiltrate my computer, he can get this last piece of info, and bring down the number of possibilities, reducing entropy. 39 | 40 | Entropy is measured by **LOG(possibilities;2)** and so LOG(5,35088E+19; 2) = 65 bits. 41 | 42 | Is it enough? Probably. Assuming your attacker does not know more information about the realm of possibilities. 43 | 44 | But since the hash of a public key is 20 bytes = 160 bits, it is smaller than the total universe of the addresses. You might do better. 45 | 46 | > **Note:** Adding entropy is linearly harder, cracking entropy is exponentially harder 47 | 48 | An interesting way of generating entropy quickly is by asking human intervention. (Moving the mouse.) 49 | 50 | If you don’t completely trust the platform PRNG (wich is not that unlikely](http://android-developers.blogspot.fr/2013/08/some-securerandom-thoughts.html)), you can add entropy to the PRNG output that NStratis is using. 51 | 52 | ```cs 53 | RandomUtils.AddEntropy("hello"); 54 | RandomUtils.AddEntropy(new byte[] { 1, 2, 3 }); 55 | var nsaProofKey = new Key(); 56 | ``` 57 | 58 | What NStratis does when you call **AddEntropy(data)** is: 59 | **additionalEntropy = SHA(SHA(data) ^ additionalEntropy)** 60 | 61 | Then when you generate a new number: 62 | **result = SHA(PRNG() ^ additionalEntropy)** 63 | 64 | ## Key Derivation Function {#key-derivation-function} 65 | 66 | However, what is most important is not the number of possibilities. It is the time that an attacker would need to successfully break your key. That’s where KDF enters the game. 67 | 68 | KDF, or **Key Derivation Function** is a way to have a stronger key, even if your entropy is low. 69 | 70 | Imagine that you want to generate a seed, and the attacker knows that there are 10.000.000 possibilities. 71 | Such a seed would be normally cracked pretty easily. 72 | 73 | But what if you could make the enumeration slower? 74 | A KDF is a hash function that waste computing resources on purpose. 75 | Here is an example: 76 | 77 | ```cs 78 | var derived = SCrypt.BitcoinComputeDerivedKey("hello", new byte[] { 1, 2, 3 }); 79 | RandomUtils.AddEntropy(derived); 80 | ``` 81 | 82 | Even if your attacker knows that your source of entropy is 5 letters, he will need to run Scrypt to check a possibility, which take 5 seconds on my computer. 83 | 84 | The bottom line is: There is nothing paranoid in distrusting a PRNG, and you can mitigate an attack by both adding entropy and also using a KDF. 85 | Keep in mind that an attacker can decrease entropy by gathering information about you or your system. 86 | If you use the timestamp as entropy source, then he can decrease the entropy by knowing you generated the key last week, and that you only use your computer between 9am and 6pm. 87 | 88 | In the previous part I talked quickly about a special KDF called **Scrypt.** As I said, the goal of a KDF is to make brute force costly. 89 | 90 | So it should be no surprise for you that a standard already exists for encrypting your private key with a password using a KDF. This is [BIP38](http://www.codeproject.com/Articles/775226/NBitcoin-Cryptography-Part). 91 | 92 | ![](../assets/EncryptedKey.png) 93 | 94 | ```cs 95 | var privateKey = new Key(); 96 | var bitcoinPrivateKey = privateKey.GetWif(Network.Main); 97 | Console.WriteLine(bitcoinPrivateKey); // L1tZPQt7HHj5V49YtYAMSbAmwN9zRjajgXQt9gGtXhNZbcwbZk2r 98 | BitcoinEncryptedSecret encryptedBitcoinPrivateKey = bitcoinPrivateKey.Encrypt("password"); 99 | Console.WriteLine(encryptedBitcoinPrivateKey); // 6PYKYQQgx947Be41aHGypBhK6TA5Xhi9TdPBkatV3fHbbKrdDoBoXFCyLK 100 | var decryptedBitcoinPrivateKey = encryptedBitcoinPrivateKey.GetSecret("password"); 101 | Console.WriteLine(decryptedBitcoinPrivateKey); // L1tZPQt7HHj5V49YtYAMSbAmwN9zRjajgXQt9gGtXhNZbcwbZk2r 102 | 103 | Console.ReadLine(); 104 | ``` 105 | 106 | Such encryption is used in two different cases: 107 | 108 | * You do not trust your storage provider (they can get hacked) 109 | * You are storing the key on the behalf of somebody else (and you do not want to know his key) 110 | 111 | If you own your storage, then encrypting at the database level might be enough. 112 | 113 | Be careful if your server takes care of decrypting the key, an attacker might attempt to DDOS your server by forcing it to decrypt lots of keys. 114 | 115 | Delegate decryption to the ultimate user when you can. 116 | 117 | ## Like the good ol’ days {#like-the-good-ol-days} 118 | 119 | First, why generate several keys? 120 | The main reason is privacy. Since you can see the balance of all addresses, it is better to use a new address for each transaction. 121 | 122 | However, in practice, you can also generate keys for each contact which makes this a simple way to identify your payer without leaking too much privacy. 123 | 124 | You can generate key, like you did from the beginning: 125 | 126 | ```cs 127 | var privateKey = new Key() 128 | ``` 129 | 130 | However, you have two problems with that: 131 | 132 | * All backups of your wallet that you have will become outdated when you generate a new key. 133 | * You cannot delegate the address creation process to an untrusted peer. 134 | 135 | If you are developing a web wallet and generate key on behalf of your users, and one user get hacked, she will immediately start suspecting you. 136 | 137 | ## BIP38 (Part 2) {#bip38-part-2} 138 | 139 | We already saw BIP38 for encrypting a key, however this BIP is in reality two ideas in one document. 140 | 141 | The second part of the BIP, shows how you can delegate Key and Address creation to an untrusted peer. It will fix one of our concerns. 142 | 143 | **The idea is to generate a PassphraseCode to the key generator. With this PassphraseCode, he will be able to generate encrypted keys on your behalf, without knowing your password, nor any private key. ** 144 | 145 | This **PassphraseCode** can be given to your key generator in WIF format. 146 | 147 | > **Tip**: In NStratis, all types prefixed by “Stratis” are Base58 (WIF) data. 148 | 149 | So, as a user that wants to delegate key creation, first you will create the **PassphraseCode**. 150 | 151 | ![](../assets/PassphraseCode.png) 152 | 153 | ```cs 154 | var passphraseCode = new StratisPassphraseCode("my secret", Network.Main, null); 155 | ``` 156 | 157 | **You then give this passphraseCode to a third party key generator.** 158 | 159 | The third party will then generate new encrypted keys for you. 160 | 161 | ![](../assets/PassphraseCodeToEncryptedKeys.png) 162 | 163 | ```cs 164 | EncryptedKeyResult encryptedKeyResult = passphraseCode.GenerateEncryptedSecret(); 165 | ``` 166 | 167 | This **EncryptedKeyResult** has lots of information: 168 | 169 | ![](../assets/EncryptedKeyResult.png) 170 | 171 | First: the **generated stratis address**, 172 | ```cs 173 | var generatedAddress = encryptedKeyResult.GeneratedAddress; // 14KZsAVLwafhttaykXxCZt95HqadPXuz73 174 | ``` 175 | then the **EncryptedKey** itself, (as we have seen in the previous, **Key Encryption** lesson), 176 | ```cs 177 | var encryptedKey = encryptedKeyResult.EncryptedKey; // 6PnWtBokjVKMjuSQit1h1Ph6rLMSFz2n4u3bjPJH1JMcp1WHqVSfr5ebNS 178 | ``` 179 | and last but not the least, the **ConfirmationCode**, so that the third party can prove that the generated key and address correspond to your password. 180 | ```cs 181 | var confirmationCode = encryptedKeyResult.ConfirmationCode; // cfrm38VUcrdt2zf1dCgf4e8gPNJJxnhJSdxYg6STRAEs7QuAuLJmT5W7uNqj88hzh9bBnU9GFkN 182 | ``` 183 | 184 | As the owner, once you receive this information, you need to check that the key generator did not cheat by using **ConfirmationCode.Check**, then get your private key with your password: 185 | 186 | ```cs 187 | Console.WriteLine(confirmationCode.Check("my secret", generatedAddress)); // True 188 | var bitcoinPrivateKey = encryptedKey.GetSecret("my secret"); 189 | Console.WriteLine(bitcoinPrivateKey.GetAddress() == generatedAddress); // True 190 | Console.WriteLine(bitcoinPrivateKey); // KzzHhrkr39a7upeqHzYNNeJuaf1SVDBpxdFDuMvFKbFhcBytDF1R 191 | ``` 192 | 193 | So, we have just seen how the third party can generate encrypted key on your behalf, without knowing your password and private key. 194 | 195 | ![](../assets/ThirdPartyKeyGeneration.png) 196 | 197 | However, one problem remains: 198 | 199 | * All backups of your wallet that you have will become outdated when you generate a new key. 200 | 201 | BIP 32, or Hierarchical Deterministic Wallets (HD wallets) proposes another solution, and is more widely supported. 202 | 203 | ## HD Wallet (BIP 32) {#hd-wallet-bip-32} 204 | 205 | Let’s keep in mind the problems that we want to resolve: 206 | 207 | * Prevent outdated backups 208 | * Delegating key / address generation to an untrusted peer 209 | 210 | A “Deterministic” wallet would fix our backup problem. With such wallet, you would have to save only the seed. From this seed, you can generate the same series of private keys over and over. 211 | 212 | This is what the “Deterministic” stands for. 213 | As you can see, from the master key, I can generate new keys: 214 | 215 | ```cs 216 | ExtKey masterKey = new ExtKey(); 217 | Console.WriteLine("Master key : " + masterKey.ToString(Network.Main)); 218 | for (int i = 0; i < 5; i++) 219 | { 220 | ExtKey key = masterKey.Derive((uint)i); 221 | Console.WriteLine("Key " + i + " : " + key.ToString(Network.Main)); 222 | } 223 | ``` 224 | 225 | ``` 226 | Master key : xprv9s21ZrQH143K3JneCAiVkz46BsJ4jUdH8C16DccAgMVfy2yY5L8A4XqTvZqCiKXhNWFZXdLH6VbsCsqBFsSXahfnLajiB6ir46RxgdkNsFk 227 | Key 0 : xprv9tvBA4Kt8UTuEW9Fiuy1PXPWWGch1cyzd1HSAz6oQ1gcirnBrDxLt8qsis6vpNwmSVtLZXWgHbqff9rVeAErb2swwzky82462r6bWZAW6Ty 228 | Key 1 : xprv9tvBA4Kt8UTuHyzrhkRWh9xTavFtYoWhZTopNHGJSe3KomssRrQ9MTAhVWKFp4d7D8CgmT7TRzauoAZXp3xwHQfxr7FpXfJKpPDUtiLdmcF 229 | Key 2 : xprv9tvBA4Kt8UTuLoEZPpW9fBEzC3gfTdj6QzMp8DzMbAeXgDHhSMmdnxSFHCQXycFu8FcqTJRm2kamjeE8CCKzbiXyoKWZ9ihiF7J5JicgaLU 230 | Key 3 : xprv9tvBA4Kt8UTuPwJQyxuZoFj9hcEMCoz7DAWLkz9tRMwnBDiZghWePdD7etfi9RpWEWQjKCM8wHvKQwQ4uiGk8XhdKybzB8n2RVuruQ97Vna 231 | Key 4 : xprv9tvBA4Kt8UTuQoh1dQeJTXsmmTFwCqi4RXWdjBp114rJjNtPBHjxAckQp3yeEFw7Gf4gpnbwQTgDpGtQgcN59E71D2V97RRDtxeJ4rVkw4E 232 | Key 5 : xprv9tvBA4Kt8UTuTdiEhN8iVDr5rfAPSVsCKpDia4GtEsb87eHr8yRVveRhkeLEMvo3XWL3GjzZvncfWVKnKLWUMNqSgdxoNm7zDzzD63dxGsm 233 | ``` 234 | 235 | You only need to save the **masterKey**, since you can generate the same suite of private keys over and over. 236 | 237 | As you can see, these keys are **ExtKey** and not **Key** as you are used to. However, this should not stop you since you have the real private key inside: 238 | 239 | ![](../assets/ExtKey.png) 240 | 241 | You can go back from a **Key** to an **ExtKey** by supplying the **Key** and the **ChainCode** to the **ExtKey** constructor. This works as follows: 242 | 243 | ```cs 244 | ExtKey extKey = new ExtKey(); 245 | byte[] chainCode = extKey.ChainCode; 246 | Key key = extKey.PrivateKey; 247 | 248 | ExtKey newExtKey = new ExtKey(key, chainCode); 249 | ``` 250 | 251 | The **base58** type equivalent of **ExtKey** is called **StratisExtKey**. 252 | 253 | But how can we solve our second problem: delegating address creation to a peer that can potentially be hacked (like a payment server)? 254 | 255 | The trick is that you can “neuter” your master key, then you have a public (without private key) version of the master key. From this neutered version, a third party can generate public keys without knowing the private key. 256 | 257 | ```cs 258 | ExtPubKey masterPubKey = masterKey.Neuter(); 259 | for (int i = 0 ; i < 5 ; i++) 260 | { 261 | ExtPubKey pubkey = masterPubKey.Derive((uint)i); 262 | Console.WriteLine("PubKey " + i + " : " + pubkey.ToString(Network.Main)); 263 | } 264 | ``` 265 | 266 | ``` 267 | PubKey 0 : xpub67uQd5a6WCY6A7NZfi7yGoGLwXCTX5R7QQfMag8z1RMGoX1skbXAeB9JtkaTiDoeZPprGH1drvgYcviXKppXtEGSVwmmx4pAdisKv2CqoWS 268 | PubKey 1 : xpub67uQd5a6WCY6CUeDMBvPX6QhGMoMMNKhEzt66hrH6sv7rxujt7igGf9AavEdLB73ZL6ZRJTRnhyc4BTiWeXQZFu7kyjwtDg9tjRcTZunfeR 269 | PubKey 2 : xpub67uQd5a6WCY6Dxbqk9Jo9iopKZUqg8pU1bWXbnesppsR3Nem8y4CVFjKnzBUkSVLGK4defHzKZ3jjAqSzGAKoV2YH4agCAEzzqKzeUaWJMW 270 | PubKey 3 : xpub67uQd5a6WCY6HQKya2Mwwb7bpSNB5XhWCR76kRaPxchE3Y1Y2MAiSjhRGftmeWyX8cJ3kL7LisJ3s4hHDWvhw3DWpEtkihPpofP3dAngh5M 271 | PubKey 4 : xpub67uQd5a6WCY6JddPfiPKdrR49KYEuXUwwJJsL5rWGDDQkpPctdkrwMhXgQ2zWopsSV7buz61e5mGSYgDisqA3D5vyvMtKYP8S3EiBn5c1u4 272 | ``` 273 | 274 | So imagine that your payment server generates pubkey1, you can get the corresponding private key with your private master key. 275 | 276 | ```cs 277 | masterKey = new ExtKey(); 278 | masterPubKey = masterKey.Neuter(); 279 | 280 | //The payment server generate pubkey1 281 | ExtPubKey pubkey1 = masterPubKey.Derive((uint)1); 282 | 283 | //You get the private key of pubkey1 284 | ExtKey key1 = masterKey.Derive((uint)1); 285 | 286 | //Check it is legit 287 | Console.WriteLine("Generated address : " + pubkey1.PubKey.GetAddress(Network.Main)); 288 | Console.WriteLine("Expected address : " + key1.PrivateKey.PubKey.GetAddress(Network.Main)); 289 | ``` 290 | 291 | ``` 292 | Generated address : 1Jy8nALZNqpf4rFN9TWG2qXapZUBvquFfX 293 | Expected address : 1Jy8nALZNqpf4rFN9TWG2qXapZUBvquFfX 294 | ``` 295 | 296 | **ExtPubKey** is similar to **ExtKey** except that it holds a **PubKey** and not a **Key**. 297 | 298 | ![](../assets/ExtPubKey.png) 299 | 300 | Now we have seen how Deterministic keys solve our problems, let’s speak about what the “hierarchical” is for. 301 | 302 | In the previous exercise, we have seen that by combining master key + index we could generate another key. We call this process **Derivation**, master key is the **parent key**, and the generated key is called **child key**. 303 | 304 | However, you can also derivate children from the child key. This is what the “hierarchical” stands for. 305 | 306 | This is why conceptually more generally you can say: Parent Key + KeyPath => Child Key 307 | 308 | ![](../assets/Derive1.png) 309 | 310 | ![](../assets/Derive2.png) 311 | 312 | 313 | In this diagram, you can derivate Child(1,1) from parent in two different way: 314 | 315 | ```cs 316 | ExtKey parent = new ExtKey(); 317 | ExtKey child11 = parent.Derive(1).Derive(1); 318 | ``` 319 | 320 | Or 321 | 322 | ```cs 323 | ExtKey parent = new ExtKey(); 324 | ExtKey child11 = parent.Derive(new KeyPath("1/1")); 325 | ``` 326 | 327 | So in summary: 328 | 329 | ![](../assets/DeriveKeyPath.png) 330 | 331 | It works the same for **ExtPubKey**. 332 | 333 | Why do you need hierarchical keys? Because it might be a nice way to classify the type of your keys for multiple accounts. More on [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki). 334 | 335 | It also permits segmenting account rights across an organization. 336 | 337 | Imagine you are CEO of a company. You want control over all wallets, but you don’t want the Accounting department to spend the money from the Marketing department. 338 | 339 | So your first idea would be to generate one hierarchy for each department. 340 | 341 | ![](../assets/CeoMarketingAccounting.png) 342 | 343 | However, in such case, **Accounting** and **Marketing** would be able to recover the CEO’s private key. 344 | 345 | We define such child keys as **non-hardened**. 346 | 347 | ![](../assets/NonHardened.png) 348 | 349 | ```cs 350 | ExtKey ceoKey = new ExtKey(); 351 | Console.WriteLine("CEO: " + ceoKey.ToString(Network.Main)); 352 | ExtKey accountingKey = ceoKey.Derive(0, hardened: false); 353 | 354 | ExtPubKey ceoPubkey = ceoKey.Neuter(); 355 | 356 | //Recover ceo key with accounting private key and ceo public key 357 | ExtKey ceoKeyRecovered = accountingKey.GetParentExtKey(ceoPubkey); 358 | Console.WriteLine("CEO recovered: " + ceoKeyRecovered.ToString(Network.Main)); 359 | ``` 360 | 361 | ``` 362 | CEO: xprv9s21ZrQH143K2XcJU89thgkBehaMqvcj4A6JFxwPs6ZzGYHYT8dTchd87TC4NHSwvDuexuFVFpYaAt3gztYtZyXmy2hCVyVyxumdxfDBpoC 363 | CEO recovered: xprv9s21ZrQH143K2XcJU89thgkBehaMqvcj4A6JFxwPs6ZzGYHYT8dTchd87TC4NHSwvDuexuFVFpYaAt3gztYtZyXmy2hCVyVyxumdxfDBpoC 364 | ``` 365 | 366 | In other words, a **non-hardened key** can “climb” the hierarchy.**Non-hardened keys** should only be used for categorizing accounts that belongs to a **single control**. 367 | 368 | So in our case, the CEO should create a **hardened key**, so the accounting department will not be able to climb. 369 | 370 | ```cs 371 | ExtKey ceoKey = new ExtKey(); 372 | Console.WriteLine("CEO: " + ceoKey.ToString(Network.Main)); 373 | ExtKey accountingKey = ceoKey.Derive(0, hardened: true); 374 | 375 | ExtPubKey ceoPubkey = ceoKey.Neuter(); 376 | 377 | ExtKey ceoKeyRecovered = accountingKey.GetParentExtKey(ceoPubkey); //Crash 378 | ``` 379 | 380 | You can also create hardened keys by via the **ExtKey.Derivate**(**KeyPath)**, by using an apostrophe after a child’s index: 381 | 382 | ```cs 383 | var nonHardened = new KeyPath("1/2/3"); 384 | var hardened = new KeyPath("1/2/3'"); 385 | ``` 386 | 387 | So let’s imagine that the Accounting Department generates 1 parent key for each customer, and a child for each of the customer’s payments. 388 | 389 | As the CEO, you want to spend the money on one of these addresses. Here is how you would proceed. 390 | 391 | ```cs 392 | ceoKey = new ExtKey(); 393 | string accounting = "1'"; 394 | int customerId = 5; 395 | int paymentId = 50; 396 | KeyPath path = new KeyPath(accounting + "/" + customerId + "/" + paymentId); 397 | //Path : "1'/5/50" 398 | ExtKey paymentKey = ceoKey.Derive(path); 399 | ``` 400 | 401 | ## Mnemonic Code for HD Keys (BIP39) {#mnemonic-code-for-hd-keys-bip39} 402 | 403 | As you have seen, generating HD keys is easy. However, what if we want an easy way to transmit such key by telephone or hand writing? 404 | 405 | Cold wallets like Trezor, generate the HD Keys from a sentence that can easily be written down. They call such sentence “the seed” or “mnemonic”. And it can eventually be protected by a password or a PIN. 406 | ![](../assets/Trezor.png) 407 | 408 | The language that you use to generate your easy to write sentence is called a **Wordlist** 409 | 410 | ![](../assets/RootKey.png) 411 | ```cs 412 | Mnemonic mnemo = new Mnemonic(Wordlist.English, WordCount.Twelve); 413 | ExtKey hdRoot = mnemo.DeriveExtKey("my password"); 414 | Console.WriteLine(mnemo); 415 | ``` 416 | 417 | ```minute put grant neglect anxiety case globe win famous correct turn link``` 418 | 419 | Now, if you have the mnemonic and the password, you can recover the **hdRoot** key. 420 | 421 | ```cs 422 | mnemo = new Mnemonic("minute put grant neglect anxiety case globe win famous correct turn link", 423 | Wordlist.English); 424 | hdRoot = mnemo.DeriveExtKey("my password"); 425 | ``` 426 | 427 | Currently supported **wordlist** are, English, Japanese, Spanish, Chinese (simplified and traditional). 428 | 429 | ## Dark Wallet {#dark-wallet} 430 | 431 | This name is unfortunate since there is nothing dark about it, and it attracts unwanted attention and concerns. Dark Wallet is a practical solution that fix our two initial problems: 432 | 433 | * Prevent outdated backups 434 | * Delegating key / address generation to an untrusted peer 435 | 436 | But it has a bonus killer feature. 437 | 438 | You have to share only one address with the world (called **StealthAddress**), without leaking any privacy. 439 | 440 | Let’s remind ourselves that if you share one **StratisAddress** with everybody, then all can see your balance by consulting the blockchain… That’s not the case with a **StealthAddress**. 441 | 442 | Its a real shame that it was labeled as **dark** since it solves partially the important problem of privacy leaking caused by the pseudo-anonymity of Stratis. A better name would have been: **One Address**. 443 | 444 | In Dark Wallet terminology, here are the different actors: 445 | 446 | * The **Payer** knows the **StealthAddress** of the **Receiver** 447 | * The **Receiver** knows the **Spend Key**, a secret that will allow him to spend the coins he receives from one of such transaction. 448 | * **Scanner** knows the **Scan Key**, a secret that allows him to detect the transactions those belong to the **Receiver**. 449 | 450 | The rest is operational details.Underneath, this **StealthAddress** is composed of one or several **Spend PubKey** (for multi sig), and one **Scan PubKey**. 451 | 452 | ![](../assets/StealthAddress.png) 453 | 454 | ```cs 455 | var scanKey = new Key(); 456 | var spendKey = new Key(); 457 | BitcoinStealthAddress stealthAddress 458 | = new BitcoinStealthAddress 459 | ( 460 | scanKey: scanKey.PubKey, 461 | pubKeys: new[] { spendKey.PubKey }, 462 | signatureCount: 1, 463 | bitfield: null, 464 | network: Network.Main); 465 | ``` 466 | 467 | The **payer**, will take your **StealthAddress**, generate a temporary key called **Ephem Key** and will generate a **Stealth Pub Key**, from which the Stratis address to which the payment will be done is generated. 468 | 469 | ![](../assets/EphemKey.png) 470 | 471 | Then, he will package the **Ephem PubKey** in a **Stealth Metadata** object embedded that in the OP_RETURN of the transaction (as we have done for the first challenge) 472 | 473 | He will also add the output to the generated bitcoin address. (the address of the **Stealth pub key**) 474 | 475 | ![](../assets/StealthMetadata.png) 476 | 477 | ```cs 478 | var ephemKey = new Key(); 479 | Transaction transaction = new Transaction(); 480 | stealthAddress.SendTo(transaction, Money.Coins(1.0m), ephemKey); 481 | Console.WriteLine(transaction); 482 | ``` 483 | 484 | The creation of the **EphemKey** being an implementation detail, you can omit it, NStratis will generate one automatically: 485 | 486 | ```cs 487 | Transaction transaction = new Transaction(); 488 | stealthAddress.SendTo(transaction, Money.Coins(1.0m)); 489 | Console.WriteLine(transaction); 490 | ``` 491 | 492 | ```json 493 | { 494 | "hash": "7772b0ad19acd1bd2b0330238a898fe021486315bd1e15f4154cd3931a4940f9", 495 | "ver": 1, 496 | "vin_sz": 0, 497 | "vout_sz": 2, 498 | "lock_time": 0, 499 | "size": 93, 500 | "in": [], 501 | "out": [ 502 | { 503 | "value": "0.00000000", 504 | "scriptPubKey": "OP_RETURN 060000000002b9266f15e8c6598e7f25d3262969a774df32b9b0b50fea44fc8d914c68176f3e" 505 | }, 506 | { 507 | "value": "1.00000000", 508 | "scriptPubKey": "OP_DUP OP_HASH16051f68af989f5bf24259c519829f46c7f2935b756 OP_EQUALVERIFY OP_CHECKSIG" 509 | } 510 | ] 511 | } 512 | ``` 513 | 514 | Then the payer add and signs the inputs, then sends the transaction on the network. 515 | 516 | The **Scanner** knowing the **StealthAddress** and the **Scan Key** can recover the **Stealth PubKey** and so expected **StratisAddress** payment. 517 | 518 | ![](../assets/ScannerRecover.png) 519 | 520 | Then the scanner checks if one of the output of the transaction correspond to such address. If it is, then **Scanner** notifies the **Receiver** about the transaction. 521 | 522 | The **Receiver** can then get the private key of the address with his **Spend Key**. 523 | 524 | ![](../assets/ReceiverStealth.png) 525 | 526 | The code explaining how, as a Scanner, to scan a transaction and how, as a Receiver, to uncover the private key, will be explained later in the **TransactionBuilder** (Other types of ownership) part. 527 | 528 | It should be noted that a **StealthAddress** can have multiple **spend pubkeys**, in which case, the address represent a multi sig. 529 | 530 | One limit of Dark Wallet is the use of **OP_RETURN**, so we can’t easily embed arbitrary data in the transaction as we have done for in Stratis Transfer. (Current Stratis rules allows only one OP_RETURN of 40 bytes, soon 80, per transaction) 531 | 532 | > ([Stackoverflow](http://bitcoin.stackexchange.com/a/29648/26859)) As I understand it, the "stealth address" is intended to address a very specific problem. If you wish to solicit payments from the public, say by posting a donation address on your website, then everyone can see on the block chain that all those payments went to you, and perhaps try to track how you spend them. 533 | > 534 | With a stealth address, you ask payers to generate a unique address in such a way that you (using some additional data which is attached to the transaction) can deduce the corresponding private key. So although you publish a single "stealth address" on your website, the block chain sees all your incoming payments as going to separate addresses and has no way to correlate them. (Of course, any individual payer knows their payment went to you, and can trace how you spend it, but they don't learn anything about other people's payments to you.) 535 | > 536 | But you can get the same effect another way: just give each payer a unique address. Rather than posting a single public donation address on your website, have a button that generates a new unique address and saves the private key, or selects the next address from a long list of pre-generated addresses (whose private keys you hold somewhere safe). Just as before, the payments all go to separate addresses and there is no way to correlate them, nor for one payer to see that other payments went to you. 537 | > 538 | So the only difference with stealth addresses is essentially to move the chore of producing a unique address from the server to the client. Indeed, in some ways stealth addresses may be worse, since very few people use them, and if you are known to be one of them, it will be easier to connect stealth transactions with you. 539 | > 540 | It doesn't provide "100% anonymity". The fundamental anonymity weakness of Bitcoin remains - that everyone can follow the chain of payments, and if you know something about one transaction or the parties to it, you can deduce something about where those coins came from or where they went. 541 | -------------------------------------------------------------------------------- /other_types_of_asset/README.md: -------------------------------------------------------------------------------- 1 | # Other types of asset {#other-types-of-asset} 2 | 3 | In the previous chapters, we have seen several types of ownership. You have seen all the different kinds of ownership and proof of ownership, and understand how stratis can be coded to invent new kinds of ownership. 4 | -------------------------------------------------------------------------------- /other_types_of_asset/colored_coins.md: -------------------------------------------------------------------------------- 1 | ## Colored Coins {#colored-coins} 2 | 3 | So until now, you have seen how to exchange Stratis on the network. However you can use the Stratis network for transferring and exchanging any type of assets. 4 | 5 | We call such assets “colored coins”. 6 | As far as the Blockchain is concerned, there is no difference between a Coin and a Colored Coin. 7 | 8 | A colored coin is represented by a standard **TxOut**. Most of the time, such **TxOut** have a residual Stratis value called “Dust”. (600 satoshi) 9 | 10 | The real value of a colored coin reside in what the **issuer** of the coin will exchange against it. 11 | 12 | ![](../assets/ColoredCoin.png) 13 | 14 | Since a colored coin is nothing but a standard coin with special meaning, it follows all what you saw about proof of ownership and the **TransactionBuilder** stays true. You can transfer a colored coin with exactly the same rules as before. 15 | 16 | As far as the blockchain is concerned, a **Colored Coin** is a **Coin** like all others. 17 | 18 | You can represent several type of asset with a colored coin: company shares, bonds, stocks, votes. 19 | 20 | But no matter what type of asset you will represent, there will always have a trust relationship between the **issuer** of the asset and the **owner**. 21 | If you own some company share, then the company might decide to not send you dividends. 22 | If you own a bond, then the bank might not exchange it at maturity. 23 | 24 | However, a violation of contract might be automatically detected with the help of **Ricardian Contracts**. 25 | A **Ricardian Contract** is a contract signed by the issuer with the rights attached to the asset. Such contract can be either human readable (pdf), but also structured (json), so tools can automatically prove any violation. 26 | The **issuer** can’t change the **ricardian contract** attached to an asset. 27 | 28 | The Blockchain is only the transport medium of a financial instrument. 29 | The innovation is that everyone can create and transfer its own asset without intermediary, whereas traditional asset transport medium (clearing houses), are either heavily regulated, or purposefully kept secret, and closed to the general public. 30 | 31 | **Open Asset** is the name of the protocol created by Flavien Charlon that describes how to **transfer** and **emit** colored coins on the Blockchain. 32 | Other protocols exist, but Open Asset is the easiest and flexible and the only one supported by **NStratis**. 33 | 34 | In the rest of the book, I will not go in the details of the Open Asset protocol, the GitHub page of the specification is better suited to this need. 35 | -------------------------------------------------------------------------------- /other_types_of_asset/issuing_an_asset.md: -------------------------------------------------------------------------------- 1 | ## Issuing an Asset {#issuing-an-asset} 2 | 3 | ### Objective {#objective} 4 | 5 | For the purpose of this exercise, I will emit **BlockchainProgramming coins**. 6 | 7 | You get **one of these BlockchainProgramming coins** for every **0.004 stratis** you send me. 8 | **One more** if you add some kind words. 9 | Furthermore this is a great opportunity to make it in to the [Hall of The Makers](http://n.stratis.ninja/). 10 | 11 | Let’s see how I would code such feature. 12 | 13 | ### Issuance Coin {#issuance-coin} 14 | 15 | In Open Asset, the Asset ID is derived from the issuer's **ScriptPubKey**. 16 | If you want to issue a Colored Coin, you need to prove ownership of such **ScriptPubKey**. And the only way to do that on the Blockchain is by spending a coin belonging to such **ScriptPubKey**. 17 | 18 | The coin that you will choose to spend for issuing colored coins is called “**Issuance Coin**” in **NStratis**. 19 | I want to emit an Asset from the book stratis address: [1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB](https://www.smartbit.com.au/address/1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB). 20 | 21 | Take a look at my balance, I decided to use the following coin for issuing assets. 22 | 23 | ```json 24 | { 25 | "transactionId": "eb49a599c749c82d824caf9dd69c4e359261d49bbb0b9d6dc18c59bc9214e43b", 26 | "index": 0, 27 | "value": 2000000, 28 | "scriptPubKey": "76a914c81e8e7b7ffca043b088a992795b15887c96159288ac", 29 | "redeemScript": null 30 | } 31 | ``` 32 | 33 | Here is how to create my 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 | Now I need to build transaction and sign the transaction with the help of the **TransactionBuilder**. 46 | 47 | ```cs 48 | var nico = StratisAddress.Create("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe"); 49 | var bookKey = new StratisSecret("???????"); 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 | You can see it includes an OP_RETURN output. In fact, this is the location where information about colored coins are stuffed. 84 | 85 | Here is the format of the data in the OP_RETURN. 86 | 87 | ![](../assets/ColorMaker.png) 88 | 89 | In our case, Quantities have only 10, which is the number of Asset I issued to ```nico```. Metadata is arbitrary data. We will see that we can put an url that points to an “Asset Definition”. 90 | An **Asset Definition** is a document that describes what the Asset is. It is optional, we are not using it in our case. (We’ll come back later on it in the Ricardian Contract part.) 91 | 92 | For more information check out the [Open Asset Specification](https://github.com/OpenAssets/open-assets-protocol/blob/master/specification.mediawiki). 93 | 94 | After transaction verifications it is ready to be sent to the network. 95 | 96 | ```cs 97 | Console.WriteLine(builder.Verify(tx)); 98 | ``` 99 | 100 | ### With QBitNinja 101 | ```cs 102 | var client = new QBitNinjaClient(Network.Main); 103 | BroadcastResponse broadcastResponse = client.Broadcast(tx).Result; 104 | 105 | if (!broadcastResponse.Success) 106 | { 107 | Console.WriteLine("ErrorCode: " + broadcastResponse.Error.ErrorCode); 108 | Console.WriteLine("Error message: " + broadcastResponse.Error.Reason); 109 | } 110 | else 111 | { 112 | Console.WriteLine("Success!"); 113 | } 114 | ``` 115 | 116 | ### Or with local Stratis core 117 | 118 | ```cs 119 | using (var node = Node.ConnectToLocal(Network.Main)) //Connect to the node 120 | { 121 | node.VersionHandshake(); //Say hello 122 | //Advertize your transaction (send just the hash) 123 | node.SendMessage(new InvPayload(InventoryType.MSG_TX, tx.GetHash())); 124 | //Send it 125 | node.SendMessage(new TxPayload(tx)); 126 | Thread.Sleep(500); //Wait a bit 127 | } 128 | ``` 129 | 130 | My Stratis Wallet have both, the book address and the “Nico” address. 131 | 132 | ![](../assets/NicoWallet.png) 133 | 134 | As you can see, Stratis Core only shows the 0.0001 Stratis of fees I paid, and ignore the 600 Stratis coin because of spam prevention feature. 135 | 136 | This classical Stratis wallet knows nothing about Colored Coins. 137 | Worse: If a classical Stratis wallet spend a colored coin, it will destroy the underlying asset and transfer only the Stratis value of the **TxOut**. (600 satoshi) 138 | 139 | For preventing a user from sending Colored Coin to a wallet that do not support it, Open Asset have its own address format, that only colored coin wallets understand. 140 | 141 | ```cs 142 | nico = StratisAddress.Create("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe"); 143 | Console.WriteLine(nico.ToColoredAddress()); 144 | ``` 145 | 146 | ``` 147 | akFqRqfdmAaXfPDmvQZVpcAQnQZmqrx4gcZ 148 | ``` 149 | 150 | Now, you can take a look on an Open Asset compatible wallet like Coinprism, and see my asset correctly detected: 151 | 152 | ![](../assets/Coinprism.png) 153 | 154 | As I have told you before, the Asset ID is derived from the issuer’s **ScriptPubKey**, here is how to get it in code: 155 | 156 | ```cs 157 | var book = StratisAddress.Create("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB"); 158 | var assetId = new AssetId(book).GetWif(Network.Main); 159 | Console.WriteLine(assetId); // AVAVfLSb1KZf9tJzrUVpktjxKUXGxUTD4e 160 | ``` 161 | -------------------------------------------------------------------------------- /other_types_of_asset/liquid_democracy.md: -------------------------------------------------------------------------------- 1 | ## Liquid Democracy {#liquid-democracy} 2 | 3 | ### Overview {#overview} 4 | 5 | This part is a purely conceptual exercise of one application of colored coins. 6 | 7 | Let’s imagine a company where some decisions are made by a board of investors after a vote. 8 | 9 | * Some investors do not know enough about a topic, so they would like to delegate decisions about some subjects to someone else. 10 | * There is potentially a huge number of investors. 11 | * As the CEO, you want the ability to sell voting power for financing the company. 12 | * As the CEO, you want the ability to cast a vote when you decide. 13 | 14 | How Colored Coins can help to organize such a vote transparently? 15 | 16 | But before beginning, let’s talk about some downside of voting on the Blockchain: 17 | 18 | * Nobody knows the real identity of a voter. 19 | * Miners could censor (even if it would be provable, and not in their interest.) 20 | * Even if nobody knows the real identity of the voter, behavioral analysis of a voter across several vote might reveal his identity. 21 | 22 | Whether these points are relevant or not is up to the vote organizer to decide. 23 | 24 | Let’s take an overview of how we would implement that. 25 | 26 | ### Issuing voting power {#issuing-voting-power} 27 | 28 | Everything start with the founder of the company (let’s call him Boss) wanting to sell “decision power” in his company to some investors. The decision power can take the shape of a colored coin that we will call for the sake of this exercise a “Power Coin”. 29 | 30 | Let’s represent it in purple: 31 | 32 | ![](../assets/PowerCoin.png) 33 | 34 | Let’s say that three persons are interested, Satoshi, Alice and Bob. (Yes, them again) 35 | So Boss decides to sell each Power Coin at 0.1 Stratis each. 36 | 37 | Let’s start funding some money to the ```powerCoin``` address, ```satoshi```, ```alice``` and ```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 | Imagine that Alice buy 2 Power coins, here is how to create such transaction. 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 | In summary, powerCoin issues 2 Power Coins to Alice and send the change to himself. Likewise, Alice send 0.2 Stratis to powerCoin and send the change to herself. 84 | 85 | Where **GetCoins** is 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 | For some reason, Alice, might want to sell some of her voting power to Satoshi. 95 | 96 | ![](../assets/PowerCoin2.png) 97 | 98 | You can note that I am double spending the coin of Alice from the **init** transaction. 99 | ****Such thing would not be accepted on the Blockchain. However, we have not seen yet how to retrieve unspent coins from the Blockchain easily, so let’s just imagine for the sake of the exercise that the coin was not double spent. 100 | 101 | Now that Alice and Satoshi have some voting power, let’s see how Boss can run a vote. 102 | 103 | ### Running a vote {#running-a-vote} 104 | 105 | By consulting the Blockchain, Boss can at any time know **ScriptPubKeys** which owns Power Coins. 106 | So he will send Voting Coins to these owner, proportionally to their voting power, in our case, 1 voting coin to Alice and 1 voting coin to Satoshi. 107 | 108 | ![](../assets/PowerCoin3.png) 109 | 110 | First, I need to create some funds for **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 | Then, issue the voting coins. 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 {#vote-delegation} 141 | 142 | The problem is that the vote concern some financial aspect of the business, and Alice is mostly concerned by the marketing aspect. 143 | 144 | Her decision is to handout her voting coin to someone she trusts having a better judgment on financial matter. She chooses to delegate her vote to Bob. 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 | You can notice that there is no **SetChange** the reason is that the input colored coin is spent entirely, so nothing is left to be returned. 163 | 164 | ### Voting {#voting} 165 | 166 | Imagine that Satoshi is too busy and decide not to vote. Now Bob must express his decision. 167 | The vote concerns whether the company should ask for a loan to the bank for investing into new production machines. 168 | 169 | Boss says on the company’s website: 170 | 171 | Send your coins to 1HZwkjkeaoZfTSaJxDw6aKkxp45agDiEzN for yes and to 1F3sAm6ZtwLAUnj7d38pGFxtP3RVEvtsbV for no. 172 | 173 | Bob decides that the company should take the loan: 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(StratisAddress.Create("1HZwkjkeaoZfTSaJxDw6aKkxp45agDiEzN"), 188 | new AssetMoney(votingCoin, 1)) 189 | .BuildTransaction(true); 190 | ``` 191 | 192 | Now Boss can compute the result of the vote and see 1-Yes 0-No, Yes win, so he takes the loan. 193 | Every participants can also count the result by themselves. 194 | 195 | ### Alternative: Use of Ricardian Contract {#alternative-use-of-ricardian-contract} 196 | 197 | In the previous exercise, we have supposed that Boss announced the modalities of the vote out of the Blockchain, on the company’s website. 198 | 199 | This works great, but Bob needs to know that the website exists. 200 | 201 | Another solution is to publish the modalities of the vote directly on the Blockchain within an **Asset Definition File**, so some software can automatically get it and present it to Bob. 202 | 203 | The only piece of code that would have changed is during the issuance of the Voting Coins to voters. 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 | In such case, Bob can see that during the issuance of his voting coin, an **Asset Definition File** was published, which is nothing more than a JSON document whose schema is partially [specified in Open Asset](https://github.com/OpenAssets/open-assets-protocol/blob/master/asset-definition-protocol.mediawiki).The schema can be extended to have information about things like: 221 | 222 | * Expiration of the vote 223 | * Destination of the votes for each candidates 224 | * Human friendly description of it 225 | 226 | However, imagine that a hacker wants to cheat the vote. He can always modify the json document (either a man in the middle attack, physical access to boss.com, or access to Bob’s machine) so Bob is tricked and send his vote to the wrong candidate. 227 | 228 | Transforming the **Asset Definition File** into a **Ricardian Contract** by signing it would make any modification immediately detectable by Bob’s software. (See [Proof Of Authenticity](https://github.com/OpenAssets/open-assets-protocol/blob/master/asset-definition-protocol.mediawiki) in the Asset Definition Protocol) 229 | -------------------------------------------------------------------------------- /other_types_of_asset/proof_of_burn_and_reputation.md: -------------------------------------------------------------------------------- 1 | ## Proof of Burn and Reputation {#proof-of-burn-and-reputation} 2 | 3 | The question is simple: in a P2P market were law enforcement is too expensive, how participants might minimize the probability to get scammed? 4 | 5 | OpenBaazar seems [to be the first](https://gist.github.com/dionyziz/e3b296861175e0ebea4b) trying to use proof of burn as a reputation determinant. 6 | 7 | There is several responses to that (escrow or notary/arbiter), but one that we will explore here is called Proof Of Burn. 8 | 9 | Imagine yourself in the middle age, and you live in a small village with several local merchants. 10 | One day, a traveling merchant comes to your village and sells you some goods at an unbelievable low price compared to local one. 11 | 12 | However, traveling merchant are well known for scamming people with low quality product, because losing reputation is a small price to pay for them compared to local merchants. 13 | Local Merchant invested into a nice store, advertising and their reputation. Unhappy customers can easily destroy them. But the traveling merchant, having no local store and only transient reputation do not have the incentives to not scam people. 14 | 15 | On the internet, where the creation of an identity is so cheap, all merchants are potentially as the travelling merchants from the middle age. 16 | The solution of market providers was to gather the real identity of every participant in the market, so law enforcement became possible. 17 | 18 | If you get scammed on Amazon of Ebay, your bank will most likely refund you, because they have a way to find the thief by contacting Amazon and Ebay. 19 | 20 | In a purely P2P market using Stratis, we do not have that. If you get scammed, you lose money. 21 | So how does a buyer trust the traveling merchant? 22 | The response is: by checking how much he invested into his reputation. 23 | 24 | So as a good intentioned seller, you want to inspire confidence into your customers. For that you will spend some of your wealth, and every customer will notice. This is the definition of “investing into your reputation”. 25 | 26 | Imagine you burned 50 Stratis for your reputation. And a customer want to buy 2 Stratis of goods from you. He has good reason to believe that you will not scam him, because you invested more into your reputation then what you can get out of scamming him. 27 | It becomes uneconomical for you to scam him. 28 | 29 | The technical details will surely vary and change over time, but here is an example of 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 | Once in the Blockchain, this transaction is undeniable proof that Alice invested money for her bakery. 84 | The Coin with ```ScriptPubKey OP_RETURN 4275726e7420666f722022416c6963652042616b65727922``` do not have any way to be spent, so those coins are lost forever. 85 | -------------------------------------------------------------------------------- /other_types_of_asset/ricardian_contracts.md: -------------------------------------------------------------------------------- 1 | ## Ricardian contracts {#ricardian-contracts} 2 | 3 | This part is a copy of an article I wrote on [Coinprism’s blog](http://blog.coinprism.com/2014/12/10/colored-coins-and-ricardian-contracts/). At the time of this writing, NStratis do not have any code related to Ricardian Contracts. 4 | 5 | ### What is a Ricardian Contract {#what-is-a-ricardian-contract} 6 | 7 | Generally, an asset is any object representing rights which can be redeemed to an issuer on specific conditions. 8 | 9 | * A company’s share gives right to dividends. 10 | * A bond gives right to the principal at maturity, coupons bears interest for every period. 11 | * A voting token gives right to vote decisions about an entity. (Company, election.) 12 | * Some mix are possible : A share can also be a voting token for the company’s president election. 13 | 14 | Such rights are typically enumerated inside a Contract, and signed by the issuer (and a trusted party if needed, like a notary). 15 | 16 | A Ricardian contract is a Contract which is cryptographically signed by the issuer, and cannot be dissociated from the asset. 17 | 18 | So the contract cannot be denied, tampered, and is provably signed by the issuer. 19 | Such contract can be kept confidential between the issuer and the redeemer, or published. 20 | 21 | Open Asset can already support all of that without changing the core protocol, and here is how. 22 | 23 | ### Ricardian Contract inside Open Asset {#ricardian-contract-inside-open-asset} 24 | 25 | [Here](http://iang.org/papers/ricardian_contract.html) is the formal definition of a ricardian contract: 26 | 27 | 1. A contract offered by an issuer to holders, 28 | 2. for a valuable right held by holders, and managed by the issuer, 29 | 3. easily readable by people (like a contract on paper), 30 | 4. readable by programs (parsable like a database), 31 | 5. digitally signed, 32 | 6. carries the keys and server information, and 33 | 7. allied with a unique and secure identifier. 34 | 35 | An AssetId is specified by OpenAsset in such way : 36 | 37 | ```AssetId = Hash160(ScriptPubKey)``` 38 | 39 | Let’s make such **ScriptPubKey** a P2SH as: 40 | 41 | ```ScriptPubKey = OP_HASH160 Hash(RedeemScript) OP_EQUAL``` 42 | 43 | Where: 44 | 45 | ```RedeemScript = HASH160(RicardianContract) OP_DROP IssuerScript``` 46 | 47 | **IssuerScript** refer to a classical P2PKH for a simple issuer, multi sig if issuance need several consents. (Issuer + notary for example.) 48 | 49 | It should be noted that from Stratis 0.10, IssuerScript is arbitrary and can be anything. 50 | 51 | The **RicardianContract** can be arbitrary, and kept private. Whoever holds the contract can prove that it applies to this Asset thanks to the hash in the ScriptPubKey. 52 | 53 | But let’s make such RicardianContract discoverable and verifiable by wallet clients with the Asset Definition Protocol. 54 | 55 | Let’s assume we are issuing a Voting token for candidate A, B or C. 56 | 57 | Let’s add to the Open Asset Marker, the following asset definition url: ```u=http://issuer.com/contract``` 58 | 59 | In the http://issuer.com/contract page, let’s create the following [Asset Definition File](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 | And now we can define the RicardianContract: 74 | 75 | ```RicardianContract = AssetDefinitionFile``` 76 | 77 | This terminate our RicardianContract implemented in OA. 78 | 79 | ### Check list {#check-list} 80 | 81 | * **A contract offered by an issuer to holders.** 82 | The contract is hosted by the issuer, unalterable, and signed every time the Issuer issues a new asset, 83 | 84 | * **For a valuable right held by holders, and managed by the issuer.** 85 | The right in this sample is a voting right for candidate A,B,C to redeem before 10 jan 2015. 86 | 87 | * **Easily readable by people (like a contract on paper.)** 88 | The human readable contract is in the contract_url, but the JSON might be enough. 89 | 90 | * **Readable by programs, (parsable like a database.)** 91 | The details of the vote are inside the **AssetDefinitionFile**, in JSON format, the authenticity of the contract is verified by software with the **IssuerScript**, and the hash in the **ScriptPubKey**. 92 | 93 | * **Digitally signed.** 94 | The **ScriptPubKey** is signed when the issuer issues the asset, thus, also the hash of the contract, and by extension, the contract itself. 95 | 96 | * **Carries the keys and server. informationIssuerScript** is included in the contract 97 | 98 | * **Allied with a unique and secure identifier.** 99 | The **AssetId** is defined by **Hash(ScriptPubKey)** that can’t be changed and is unique. 100 | 101 | ### What is it for? {#what-is-it-for} 102 | 103 | Without Ricardian Contract, it is easy for a malicious issuer to modify or repudiate an Asset Definition File. 104 | 105 | Ricardian Contract enforces non-repudiation, make a contract unalterable, so it facilitate arbitration matter between redeemers and issuers. 106 | 107 | Also, since the Asset Definition File can’t be changed, it becomes possible to save it on redeemer’s own storage, preventing rupture of access to the contract by a malicious issuer. 108 | -------------------------------------------------------------------------------- /other_types_of_asset/transfer_an_asset.md: -------------------------------------------------------------------------------- 1 | ## Transfer an Asset {#transfer-an-asset} 2 | 3 | So now, let’s imagine I sent you some **BlockchainProgramming Coins**. 4 | How can you send me back the coins? 5 | You need to build a **ColoredCoin**. 6 | 7 | In the sample above, let’s say I want to spend the 10 assets I received on the address “nico”. 8 | Here is the coin I want to spend: 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 | Here is how to instantiate such Colored Coin in code: 23 | 24 | ```cs 25 | var coin = new Coin( 26 | fromTxHash: new uint256("fa6db7a2e478f3a8a0d1a77456ca5c9fa593e49fd0cf65c7e349e5a4cbe58842"), 27 | fromOutputIndex: 0, 28 | amount: Money.Stratis(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 | We will show you later how you can use some web services or custom code to get the coins more easily. 35 | I also needed another coin (forFees), to pay the fees. 36 | The asset transfer is actually very easy with the **TransactionBuilder**. 37 | 38 | ```cs 39 | var book = StratisAddress.Create("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB"); 40 | var nicoSecret = new StratisSecret("??????????"); 41 | var nico = nicoSecret.GetAddress(); //15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe 42 | 43 | var forFees = new Coin( 44 | fromTxHash: new uint256("7f296e96ec3525511b836ace0377a9fbb723a47bdfb07c6bc3a6f2a0c23eba26"), 45 | fromOutputIndex: 0, 46 | amount: Money.Stratis(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 | Which basically succeed: 81 | 82 | ![](../assets/Coinprism2.png) 83 | -------------------------------------------------------------------------------- /other_types_of_asset/unit_tests.md: -------------------------------------------------------------------------------- 1 | ## Unit tests {#unit-tests} 2 | 3 | You can see that I previously hard coded the properties of **ColoredCoin**. 4 | The reason is that I only wanted to show you how to construct a **Transaction** out of **ColoredCoin** coins. 5 | 6 | In real life, you would either depend on a third party API to fetch the colored coins of a transaction or a balance. Which might be not a good idea, because it add a trust dependency to your program with the API provider. 7 | 8 | **NStratis** allows you either to depend on a web service, either to provide your own implementation for fetching the color of a **Transaction**. This allows you to have a flexible way to unit test your code, use another implementation or your own. 9 | 10 | Let’s introduce two issuers: Silver and Gold. And three participants: Bob, Alice and Satoshi. 11 | Let’s create a fake transaction that gives some stratis to Silver, Gold and Satoshi. 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** does not contain any Colored Coin issuance and Transfer. But imagine that you want to be sure of it, how would you proceed? 35 | 36 | In **NStratis**, the summary of color transfers and issuances is described by a class called **ColoredTransaction**. 37 | 38 | ![](../assets/ColoredTransaction.png) 39 | 40 | You can see that the **ColoredTransaction** class will tell you: 41 | 42 | * Which **TxIn** spends which Asset 43 | * Which **TxOut** emits which Asset 44 | * Which **TxOut** transfers which Asset 45 | 46 | But the method that interests us right now is **FetchColor**, which will permit you to extract colored information out of the transaction you gave in input. 47 | 48 | You see that it depends on a **IColoredTransactionRepository**. 49 | 50 | ![](../assets/IColoredCoinTransactionRepository.png) 51 | 52 | **IColoredTransactionRepository** is only a store that will give you the **ColoredTransaction** from the txid. However you can see that it depends on **ITransactionRepository**, which maps a Transaction id to its transaction. 53 | 54 | An implementation of **IColoredTransactionRepository** is **CoinprismColoredTransactionRepository** which is a public API for colored coins operations. 55 | However, you can easily do your own, here is how **FetchColors** works. 56 | 57 | The simplest case is: The **IColoredTransactionRepository** knows the color, in such case **FetchColors** only returns that result. 58 | 59 | ![](../assets/FetchColors.png) 60 | 61 | The second case is that the **IColoredTransactionRepository** does not know anything about the color of the transaction. 62 | So **FetchColors** will need to compute the color itself according to the open asset specification. 63 | 64 | However, for computing the color, **FetchColors** need the color of the parent transactions. 65 | So it fetch each of them on the **ITransactionRepository**, and call **FetchColors** on each of them. 66 | Once **FetchColors** has resolved the color of the parent’s recursively, it computes the transaction color, and caches the result back in the **IColoredTransactionRepository**. 67 | 68 | ![](../assets/FetchColors2.png) 69 | 70 | By doing that, future requests to fetch the color of a transaction will be resolved quickly. 71 | Some **IColoredTransactionRepository** are read-only (like **CoinprismColoredTransactionRepository** so the Put operation is ignored). 72 | 73 | So, back to our example: 74 | The trick when writing unit tests is to use an in memory **IColoredTransactionRepository**: 75 | 76 | ```cs 77 | var repo = new NoSqlColoredTransactionRepository(); 78 | ``` 79 | 80 | Now, we can put our **init** transaction inside. 81 | 82 | ```cs 83 | repo.Transactions.Put(init); 84 | ``` 85 | 86 | Note that Put is an extension methods, so you will need to add 87 | 88 | ```cs 89 | using NStratis.OpenAsset; 90 | ``` 91 | 92 | at the top of the file to get access to it. 93 | 94 | And now, you can extract the color: 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 | As expected, the **init** transaction has no inputs, issuances, transfers or destructions of Colored Coins. 111 | 112 | So now, let’s use the two coins sent to Silver and Gold as Issuance Coins. 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 is the first coin, Silver the second one. 126 | 127 | From that you can send Gold to Satoshi with the **TransactionBuilder**, as we have done in the previous exercise, and put the resulting transaction in the repository, and print the result. 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 | This means that the first **TxOut** bears 10 gold. 145 | 146 | Now imagine that **Satoshi** wants to send 4 gold to **Alice**. 147 | First, he will fetch the **ColoredCoin** out of the transaction. 148 | 149 | ```cs 150 | var goldCoin = ColoredCoin.Find(sendGoldToSatoshi, color).FirstOrDefault(); 151 | ``` 152 | 153 | Then, build a transaction like that: 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 | Except you will get the exception **NotEnoughFundsException**. 167 | The reason is that the transaction is composed of 600 stratis in input (the **goldCoin**), and 1200 stratis in output. (One **TxOut** for sending assets to Alice, and one for sending back the change to Satoshi.) 168 | 169 | This means that you are out of 600 stratis. 170 | You can fix the problem by adding the last **Coin** of 1 Stratis in the **init** transaction that belongs to **satoshi**. 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, strtis) 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 | Let’s see the transaction and its colored part: 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 | We have finally made a unit test that emits and transfers some assets without any external dependencies. 258 | 259 | You can make your own **IColoredTransactionRepository** if you don’t want to depend on a third party service. 260 | 261 | You can find more complex scenarios in [NStratis tests](https://github.com/NicolasDorier/NBitcoin/blob/master/NStratis.Tests/transaction_tests.cs), and also one of my article “[Build them all](http://www.codeproject.com/Articles/835098/NBitcoin-Build-Them-All)” in codeproject. (Like multi sig issuance and colored coin swaps.) 262 | -------------------------------------------------------------------------------- /other_types_of_ownership/README.md: -------------------------------------------------------------------------------- 1 | # Other types of ownership {#other-types-of-ownership} 2 | 3 | I will briefly talk about each type of **ScriptPubKey** you will likely see on the blockchain. Then I will explain how to sign easily each of those types in the last part of the chapter “Using the TransactionBuilder”. -------------------------------------------------------------------------------- /other_types_of_ownership/arbitrary.md: -------------------------------------------------------------------------------- 1 | ## Arbitrary {#arbitrary} 2 | 3 | From Stratis 0.10, the **RedeemScript** can be arbitrary, which means that with the script language of Stratis, you can create your own definition of what “ownership” means. 4 | 5 | For example, I can give money to whoever either knows my date of birth (dd/mm/yyyy) serialized in UTF8 or knows the private key of **1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB**. 6 | 7 | The details of the script language are out of scope, you can easily find the documentation on various websites, and it is a stack based language so everyone having done some assembler should be able to read it. 8 | 9 | > **Note:** ([nopara73](https://github.com/nopara73)) I find [Davide De Rosa's tutorial](http://davidederosa.com/basic-blockchain-programming/bitcoin-script-language-part-one/) as the most enjoyable one. 10 | 11 | So first, let’s build the **RedeemScript**, 12 | 13 | > **Note:** For this code to work right click **References** ->** Add Reference...** -> Find **System.Numerics** 14 | 15 | ```cs 16 | StratisAddress address = StratisAddress.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 | This **RedeemScript** means that there is 2 way of spending such **ScriptCoin**: either you know the data that give **birthHash** (my birthdate), either you own the stratis address. 28 | 29 | Let’s say I sent money to such **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 | So let’s create a transaction that want to spend such output: 38 | 39 | ```cs 40 | //Create spending transaction 41 | Transaction spending = new Transaction(); 42 | spending.AddInput(new TxIn(new OutPoint(tx, 0))); 43 | ``` 44 | 45 | The first option is to know my birth date and to prove it in the **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 | You can see that in the **scriptSig** I push **OP_1** so I enter in the **OP_IF** of my **RedeemScript**. 57 | Since there is no backed-in template, for creating such **scriptSig**, you can see how to build a P2SH **scriptSig** by hand. 58 | 59 | Then you can check that the **scriptSig** prove the ownership of the **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 | The second way of spending the coin is by proving ownership of **1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB**. 72 | ``` 73 | ////Option 2 : Spender knows my private key 74 | StratisSecret secret = new StratisSecret("..."); 75 | var sig = spending.SignInput(secret, scriptCoin); 76 | var p2pkhProof = PayToPubkeyHashTemplate 77 | .Instance 78 | .GenerateScriptSig(sig, secret.PrivateKey.PubKey); 79 | selectIf = OpcodeType.OP_0; //go to else 80 | scriptSig = p2pkhProof + selectIf + redeemBytes; 81 | spending.Inputs[0].ScriptSig = scriptSig; 82 | ``` 83 | 84 | And ownership is also proven: 85 | 86 | ```cs 87 | //Verify the script pass 88 | result = spending 89 | .Inputs 90 | .AsIndexedInputs() 91 | .First() 92 | .VerifyScript(tx.Outputs[0].ScriptPubKey); 93 | Console.WriteLine(result); // True 94 | /////////// 95 | ``` 96 | -------------------------------------------------------------------------------- /other_types_of_ownership/multi_sig.md: -------------------------------------------------------------------------------- 1 | ## Multi Sig {#multi-sig} 2 | 3 | It is possible to have shared ownership over coins. 4 | For that you will create a ```ScriptPubKey``` that represents a **m-of-n multi sig**, this means in order to spend the coins, **m** private keys will need to sign on the **n** different public key provided. 5 | 6 | Let’s create a multi sig with Bob, Alice, and Satoshi, where two of them are needed to spend a coin. 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 | As you can see, the ```scriptPubkey``` have the following form: ``` OP_CHECKMULTISIG``` 25 | 26 | The process for signing it is a little more complicated than just calling ```Transaction.Sign```, which does not work for multi sig. 27 | 28 | Even if we will talk more deeply about the subject, let’s use the ```TransactionBuilder``` for signing the transaction. 29 | 30 | Imagine the multi-sig ```scriptPubKey``` received a coin in a transaction called ```received```: 31 | 32 | ```cs 33 | var received = new Transaction(); 34 | received.Outputs.Add(new TxOut(Money.Coins(1.0m), scriptPubKey)); 35 | ``` 36 | 37 | Bob and Alice agree to pay Nico 1.0 Stratis for his services. 38 | So they get the ```Coin``` they received from the transaction: 39 | 40 | ```cs 41 | Coin coin = received.Outputs.AsCoins().First(); 42 | ``` 43 | 44 | ![](../assets/coin.png) 45 | 46 | Then, with the ```TransactionBuilder```, create an **unsigned transaction**. 47 | 48 | ```cs 49 | StratisAddress nico = new Key().PubKey.GetAddress(Network.Main); 50 | TransactionBuilder builder = new TransactionBuilder(); 51 | Transaction unsigned = 52 | builder 53 | .AddCoins(coin) 54 | .Send(nico, Money.Coins(1.0m)) 55 | .BuildTransaction(sign: false); 56 | ``` 57 | 58 | The transaction is not yet signed. Here is how Alice signs it: 59 | 60 | ```cs 61 | Transaction aliceSigned = 62 | builder 63 | .AddCoins(coin) 64 | .AddKeys(alice) 65 | .SignTransaction(unsigned); 66 | ``` 67 | 68 | ![](../assets/aliceSigned.png) 69 | 70 | And then Bob: 71 | 72 | ```cs 73 | Transaction bobSigned = 74 | builder 75 | .AddCoins(coin) 76 | .AddKeys(bob) 77 | .SignTransaction(aliceSigned); 78 | ``` 79 | 80 | ![](../assets/bobSigned.png) 81 | 82 | Now, Bob and Alice can combine their signature into one transaction. 83 | 84 | ```cs 85 | Transaction fullySigned = 86 | builder 87 | .AddCoins(coin) 88 | .CombineSignatures(aliceSigned, bobSigned); 89 | ``` 90 | 91 | ![](../assets/fullySigned.png) 92 | 93 | ```cs 94 | Console.WriteLine(fullySigned); 95 | ``` 96 | 97 | ```json 98 | { 99 | ... 100 | "in": [ 101 | { 102 | "prev_out": { 103 | "hash": "9df1e011984305b78210229a86b6ade9546dc69c4d25a6bee472ee7d62ea3c16", 104 | "n": 0 105 | }, 106 | "scriptSig": "0 3045022100a14d47c762fe7c04b4382f736c5de0b038b8de92649987bc59bca83ea307b1a202203e38dcc9b0b7f0556a5138fd316cd28639243f05f5ca1afc254b883482ddb91f01 3044022044c9f6818078887587cac126c3c2047b6e5425758e67df64e8d682dfbe373a2902204ae7fda6ada9b7a11c4e362a0389b1bf90abc1f3488fe21041a4f7f14f1d856201" 107 | } 108 | ], 109 | "out": [ 110 | { 111 | "value": "1.00000000", 112 | "scriptPubKey": "OP_DUP OP_HASH160 d4a0f6c5b4bcbf2f5830eabed3daa7304fb794d6 OP_EQUALVERIFY OP_CHECKSIG" 113 | } 114 | ] 115 | } 116 | 117 | ``` 118 | The transaction is now ready to be sent on the network. 119 | 120 | Even if the Stratis network supports multi sig as explained here, one question is worth asking : How can you ask a user who has no clue about Stratis to pay on satoshi/alice/bob multi sig, since such ```scriptPubKey``` can’t be represented by an easy to use Stratis Address like we have seen before? 121 | 122 | Don’t you think it would be cool if we could represent such ```scriptPubKey``` as easily and compactly as a Stratis Address? 123 | 124 | Well, this is possible and it is called a **Stratis Script Address** also called Pay to Script Hash. (P2SH) 125 | 126 | Nowadays, **native Pay To Multi Sig** as you have seen here, and **native P2PK**, are never used directly as such, they are wrapped into **Pay To Script Hash** payment. 127 | -------------------------------------------------------------------------------- /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 - Quick recap 4 | We learned that a **Stratis Address** was the **hash of a** **public key**: 5 | 6 | ```cs 7 | var publicKeyHash = new Key().PubKey.Hash; 8 | var StratisAddress = publicKeyHash.GetAddress(Network.Main); 9 | Console.WriteLine(publicKeyHash); // 41e0d7ab8af1ba5452b824116a31357dc931cf28 10 | Console.WriteLine(bitcoinAddress); // 171LGoEKyVzgQstGwnTHVh3TFTgo5PsqiY 11 | ``` 12 | 13 | We also learned that as far as the blockchain is concerned, there is no such thing as a **Stratis address**. The blockchain identifies a receiver with a **ScriptPubKey**, and such **ScriptPubKey** could be generated from the address: 14 | 15 | ```cs 16 | var scriptPubKey = StratisAddress.ScriptPubKey; 17 | Console.WriteLine(scriptPubKey); // OP_DUP OP_HASH160 41e0d7ab8af1ba5452b824116a31357dc931cf28 OP_EQUALVERIFY OP_CHECKSIG 18 | ``` 19 | 20 | And vice versa: 21 | 22 | ```cs 23 | var sameStratisAddress = scriptPubKey.GetDestinationAddress(Network.Main); 24 | ``` 25 | 26 | ### P2PK 27 | 28 | However, all **ScriptPubKey** does not represent a Stratis Address. For example the first transaction in the blockchain, called the genesis: 29 | 30 | ```cs 31 | Block genesisBlock = Network.Main.GetGenesis(); 32 | Transaction firstTransactionEver = genesisBlock.Transactions.First(); 33 | var firstOutputEver = firstTransactionEver.Outputs.First(); 34 | var firstScriptPubKeyEver = firstOutputEver.ScriptPubKey; 35 | var firstStratisAddressEver = firstScriptPubKeyEver.GetDestinationAddress(Network.Main); 36 | Console.WriteLine(firstBitcoinAddressEver == null); // True 37 | ``` 38 | 39 | ```cs 40 | Console.WriteLine(firstTransactionEver); 41 | ``` 42 | 43 | ```json 44 | { 45 | … 46 | "out": [ 47 | { 48 | "value": "50.00000000", 49 | "scriptPubKey": "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG" 50 | } 51 | ] 52 | } 53 | ``` 54 | 55 | You can see the form of the **scriptPubKey** is different: 56 | 57 | ```cs 58 | Console.WriteLine(firstScriptPubKeyEver); // 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG 59 | ``` 60 | 61 | A Stratis address is represented by: **OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG** 62 | 63 | But here we have: **<pubkey> OP_CHECKSIG** 64 | 65 | In fact, at the beginning, **public key** were used directly in the **ScriptPubKey**. 66 | 67 | ```cs 68 | var firstPubKeyEver = firstScriptPubKeyEver.GetDestinationPublicKeys().First(); 69 | Console.WriteLine(firstPubKeyEver); // 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f 70 | ``` 71 | 72 | Now we are mainly using the hash of the public key. 73 | 74 | ![](../assets/PPKH.png) 75 | 76 | ```cs 77 | key = new Key(); 78 | Console.WriteLine("Pay to public key : " + key.PubKey.ScriptPubKey); 79 | Console.WriteLine(); 80 | Console.WriteLine("Pay to public key hash : " + key.PubKey.Hash.ScriptPubKey); 81 | ``` 82 | 83 | ``` 84 | Pay to public key : 02fb8021bc7dedcc2f89a67e75cee81fedb8e41d6bfa6769362132544dfdf072d4 OP_CHECKSIG 85 | Pay to public key hash : OP_DUP OP_HASH160 0ae54d4cec828b722d8727cb70f4a6b0a88207b2 OP_EQUALVERIFY OP_CHECKSIG 86 | ``` 87 | 88 | These two types of payment are referred as **P2PK** (pay to public key) and **P2PKH** (pay to public key hash). 89 | 90 | Satoshi later decided to use P2PKH instead of P2PK for two reasons: 91 | 92 | * Elliptic Curve Cryptography, the cryptography used by your **public key** and **private key**) is vulnerable to a modified Shor's algorithm for solving the discrete logarithm problem on elliptic curves. In plain English, it means that, with a quantum computer, in theory, it is possible in some distant future to **retrieve a private key from a public key**. By publishing the public key only when the coins are spend, such attack is rendered ineffective. (Assuming addresses are not reused.) 93 | * The hash being smaller (20 bytes), it is smaller to print, and easier to embed into small storage like a QR code. 94 | 95 | Nowadays, there is no reason to use P2PK directly, but it is still used in combination with P2SH, more on this later. 96 | 97 | > ([Discussion](https://www.reddit.com/r/Bitcoin/comments/4isxjr/petition_to_protect_satoshis_coins/d30we6f)) If the early use of P2PK will not be addressed, it will have a serious impact on the Stratis price. 98 | 99 | ### Exercise 100 | ([nopara73](https://github.com/nopara73)) While reading this chapter I found the the abbreviations (P2PK, P2PKH, P2W, etc..) very confusing. 101 | My trick was to force myself to pronounce the terms fully every time I encountered them during the following lessons. Suddenly everything made much more sense. I recommend you to do the same. 102 | -------------------------------------------------------------------------------- /other_types_of_ownership/p2sh_pay_to_script_hash.md: -------------------------------------------------------------------------------- 1 | ## P2SH (Pay To Script Hash) {#p2sh-pay-to-script-hash} 2 | 3 | As seen previously, Multi-Sig works easily in code, however, before p2sh, there was no way to ask a customer to pay to a multi-sig ```scriptPubKey``` as easily as we could hand him a ```StratisAddress```. 4 | 5 | **P2SH**, or **Pay To Script Hash**, is an easy way to represent any ```scriptPubKey``` as a simple ```StratisScriptAddress```, no matter how complicated it is. 6 | 7 | In the previous part we generated this multisig: 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 | Complicated isn’t it? 26 | 27 | Instead, let’s see how such ```scriptPubKey``` would look like as a **P2SH** payment. 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 | Do you see the difference? This p2sh ```scriptPubKey``` represents the hash of my multi-sig script: ```redeemScript.Hash.ScriptPubKey``` 46 | 47 | Since it is a hash, you can easily convert it as a base58 string ```StratisScriptAddress```. 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 | Such address is understood by any client wallet. Even if such wallet does not understand what “multi sig” is. 63 | 64 | In P2SH payment, we refer as the **Redeem Script**, the ```scriptPubKey``` that got hashed. 65 | 66 | ![](../assets/RedeemScript.png) 67 | 68 | Since the payer only knows about the **Hash of the RedeemScript**, he does not know the **Redeem Script**, and so, in our case, don’t even have to know that he is sending money to a multi sig of Bob/Satoshi/Alice. 69 | 70 | Signing such transaction is similar to what we have done before. The only difference is that you have to provide the **Redeem Script** when you build the Coin for the **TransactionBuilder** 71 | 72 | Imagine that the multi sig P2SH receive a coin in a transaction called ```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 | > Warning: The payment is sent to ```redeemScript.Hash``` and not to ```redeemScript```! 88 | 89 | Then, once alice/bob/satoshi want to spend what they received, instead of creating a ```Coin``` they create a ```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 | The rest of the code concerning transaction generation and signing is exactly the same as in the previous part with native multi sig. 101 | -------------------------------------------------------------------------------- /other_types_of_ownership/p2w_over_p2sh.md: -------------------------------------------------------------------------------- 1 | ## P2W* over P2SH {#p2w-over-p2sh} 2 | 3 | While using **witness scriptPubKey** for your scripting needs is appealing, the reality is that most of nowadays wallets only support P2PKH or P2SH addresses. 4 | 5 | To harness the advantages of segwit, while being compatible with old software, P2W over P2SH is allowed. For an old node, it will look like a normal P2SH payment. 6 | 7 | You can transform any **P2W*** to a **P2W* over** **P2SH** by: 8 | 9 | 1. Replacing the **ScriptPubKey** by its P2SH equivalent. 10 | 2. The former **ScriptPubKey** will be placed as the only push in the **scriptSig** in the spending transaction, 11 | 3. All other data will be pushed in the witness of the spending transaction. 12 | 13 | Don’t worry, if this sound complicated, the TransactionBuilder will allow you to abstract the plumbing effectively. 14 | 15 | Let’s take the example of P2WPKH over P2SH, also called with the sweet name of **P2SH(P2WPKH)**. 16 | 17 | Printing the **ScriptPubKey**: 18 | 19 | ```cs 20 | var key = new Key(); 21 | Console.WriteLine(key.PubKey.WitHash.ScriptPubKey.Hash.ScriptPubKey); 22 | ``` 23 | 24 | > **Note:** that's quite an awesome line of code. 25 | 26 | Which gives us a well known P2SH **scriptPubKey**. 27 | 28 | ``` 29 | OP_HASH160 b19da5ca6e7243d4ec8eab07b713ff8768a44145 OP_EQUAL 30 | ``` 31 | 32 | Then, a signed transaction spending this output will look like: 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 | The **scriptSig** is only the push of the P2SH redeem script of the previous ScriptPubKey (in other words **key.PubKey.WitHash.ScriptPubKey**). The witness is exactly the same as a normal **P2WPKH** payment. 48 | 49 | In NStratis, signing a **P2SH(P2WPKH)** is exactly similar as signing a normal P2SH with ScriptCoin. 50 | 51 | By following the same principle, let’s see how a **P2SH(P2WSH)** looks like. You need to understand that in this case we are dealing with two different redeem scripts: The **P2SH redeem script** that needs to be put in the **scriptSig** of the spending transaction, AND the **P2WSH redeem script** that needs to be put in the witness. 52 | 53 | Let’s print the **scriptPubKey** by following the first rule: 54 | 55 | 1. Replacing the **ScriptPubKey** by its P2SH equivalent. 56 | 57 | ```cs 58 | var key = new Key(); 59 | Console.WriteLine(key.PubKey.ScriptPubKey.WitHash.ScriptPubKey.Hash.ScriptPubKey); 60 | ``` 61 | ``` 62 | OP_HASH160 d06c0058175952afecc56d26ed16558b1ed40e42 OP_EQUAL 63 | ``` 64 | > **Warning:** It makes sense, don't try any whiny ragequitting! 65 | 2. The former **ScriptPubKey** will be placed as the only push in the **scriptSig** in the spending transaction, 66 | 3. All other data will be pushed in the witness of the spending transaction, 67 | 68 | For 3\. the **‘other data’**, in the context of a P2WSH payment means the parameters of the **P2WSH redeem script** followed by a push of the **P2WSH redeem script**. 69 | 70 | ```json 71 | "in": [ 72 | { 73 | "prev_out": { 74 | "hash": "1d23fa744a26cf6433f0841e9de7e088cf95e6f953e584b98d0de6ef4216765f", 75 | "n": 0 76 | }, 77 | "scriptSig": "0020c54eb79829b2e26b71d15fd3b490b6e95cbdab361a45eed2cdfe642497480a6c", 78 | "witness": "3045022100d7570c3bf87149a0be3ba2e8bfccbdd35c3da44f741695e9962014795fabc4fc02203183cfa55a85728520b0f1ac59ac3ffa1a8526634fe619f99fac0f76016f366e01 2103146e87d7fcc81f3e044f97c6b262c01826f40a9ab9acae0f689983a5890a1f4dac" 79 | } 80 | ], 81 | 82 | ``` 83 | 84 | In summary, the P2SH Redeem Script is hashed to get the P2WSH scriptPubKey as normal P2WSH payment. Then, as a normal P2SH payment the P2WSH scriptPubKey is replaced by hashed and used to create the actual P2SH. 85 | 86 | If P2SH/P2WSH/P2SH(P2WSH)/P2SH(P2WPKH) sounds complicated to you. Fear not. 87 | NStratis, for **all of those payments type** only requires you to create a **ScriptCoin** by supplying the Redeem (P2WSH redeem or P2SH redeem) and the ScriptPubKey, exactly as explained in the **P2SH** part. 88 | 89 | As far as NStratis is concerned, you just need to feed the right transaction output you want to spend, with the right underlying redeem script, and the **TransactionBuilder** will figure out how to sign correctly as explained in the previous **Multi Sig** part and the next “**Using the TransactionBuilder**” part. 90 | 91 | ![](../assets/ScriptCoin.png) 92 | 93 | **Compatible for P2SH/P2WSH/P2SH(P2WSH)/P2SH(P2WPKH)** 94 | 95 | You can browse additional examples of P2W* payments on [http://n.bitcoin.ninja/checkscript](http://n.bitcoin.ninja/checkscript) 96 | -------------------------------------------------------------------------------- /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 | In 2015, Pieter Wuille introduced a new feature to bitcoin called **Segregated Witness** or shorter, **segwit**. Basically, Segregated Witness move the proof of ownership from the **scriptSig** part of the transaction, to a new part called the **witness** of the input. 4 | 5 | There is several reason to use this new scheme, here is a summary, for more details go to [https://bitcoincore.org/en/2016/01/26/segwit-benefits/](https://bitcoincore.org/en/2016/01/26/segwit-benefits/) 6 | 7 | * **Third party Malleability Fix:** Previously, a third party could change the transaction id of your transaction before it was confirmed. Not anymore. 8 | * **Linear sig hash scaling:** Signing a transaction would require hashing the whole transaction for every input. This was a potential DDoS vector attack for large transactions. 9 | * **Signing of input values:** The amount that is spent in an input is also signed, meaning the signer can’t be tricked about the amount of fee that is actually paid. 10 | * **Capacity increase:** It will now be possible to have more than 1MB of transactions every 10 min, up to around 1.75. 11 | * **Fraud proof:** Will be developed later, but SPV wallet will be able to validate more consensus rule than just following the longest chain. 12 | 13 | Before the transaction signature belonged to the calculation of the transaction id, not anymore. 14 | 15 | ![](../assets/segwit.png) 16 | 17 | The signature contains the same information as a P2PKH spending, but is located in the witness instead of the scriptSig. The ```scriptPubKey``` though, is modified from 18 | 19 | ``` 20 | OP_DUP OP_HASH160 0067c8970e65107ffbb436a49edd8cb8eb6b567f OP_EQUALVERIFY OP_CHECKSIG 21 | ``` 22 | 23 | To 24 | 25 | ``` 26 | 0 0067c8970e65107ffbb436a49edd8cb8eb6b567f 27 | ``` 28 | 29 | For nodes which did not upgrade, this looks like as two pushes on the stack. This means that any ```scriptSig``` can spend them. So even without the signatures, old nodes will consider such transactions valid. New nodes interprete the first push as the **witness version** and the second push as the **witness program**. 30 | 31 | But new nodes will require the signature to get the transaction verified. 32 | 33 | **In NStratis, spending a P2WPKH output is not different from spending a normal P2PKH. 34 | To get the ```ScriptPubKey``` to use from a public key, use ```PubKey.WitHash``` instead of ```PubKey.Hash```.** 35 | 36 | ```cs 37 | var key = new Key(); 38 | Console.WriteLine(key.PubKey.WitHash.ScriptPubKey); 39 | ``` 40 | 41 | Which will output your something like 42 | 43 | ``` 44 | 0 0067c8970e65107ffbb436a49edd8cb8eb6b567f 45 | ``` 46 | 47 | Signing the spending of such coin will be explained in the “Using the ```TransactionBuilder``` part”, and does not differ, in any way, from the code for signing a P2PKH output. 48 | 49 | The ```witness```, similar to the ```scriptSig``` of P2PKH, and the ```scriptSig``` empty: 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 | Once again, the semantic of P2WPKH is the same as the semantic of P2PKH, except that the signature is not placed at the same location as before. 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 | As with P2PKH/P2WPKH, the only difference between P2SH and P2WSH is about the location of what was previously in the ```scriptSig```, and the ```scriptPubKey``` being modified. 4 | 5 | The ```scriptPubKey``` is changed from something like: 6 | 7 | ```OP_HASH160 10f400e996c34410d02ae76639cbf64f4bdf2def OP_EQUAL``` 8 | 9 | To: 10 | 11 | ```0 e4d3d21bab744d90cd857f56833252000ac0fade318136b713994b9319562467``` 12 | 13 | That you can print with the following code: 14 | 15 | ```cs 16 | var key = new Key(); 17 | Console.WriteLine(key.PubKey.ScriptPubKey.WitHash.ScriptPubKey); 18 | ``` 19 | 20 | With what was previously in the ```scriptSig``` (signature + redeem script), moved to the ```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 | 36 | As the P2SH payment explained previously, P2WSH use ```ScriptCoin``` in exactly the same way to be signed. -------------------------------------------------------------------------------- /other_types_of_ownership/using_the_transactionbuilder.md: -------------------------------------------------------------------------------- 1 | ## Using the TransactionBuilder {#using-the-transactionbuilder} 2 | 3 | You have seen how the **TransactionBuilder** works when you have signed your first **P2SH** and **multi-sig** transaction. 4 | 5 | We will see how you can harness its full power, for signing more complicated transactions. 6 | 7 | With the **TransactionBuilder** you can: 8 | * Spend any 9 | * **P2PK**, **P2PKH**, 10 | * **multi-sig**, 11 | * **P2WPK**, **P2WSH**. 12 | * Spend any **P2SH** on the previous redeem script. 13 | * Spend **Stealth Coin** (DarkWallet). 14 | * Issue and transfer **Colored Coins** (open asset, following chapter). 15 | * Combine **partially signed transactions**. 16 | * Estimate the final **size** of an **unsigned transaction** and its **fees**. 17 | * Verify if a **transaction** is **fully signed**. 18 | 19 | The goal of the **TransactionBuilder** is to take **Coins** and **Keys** as input, and return back a **signed** or **partially signed transaction**. 20 | 21 | ![](../assets/SignedTransaction.png) 22 | 23 | The **TransactionBuilder** will figure out what **Coin** to use and what to sign by itself. 24 | 25 | ![](../assets/TransactionBuilder.png) 26 | 27 | The usage of the builder is done in four steps: 28 | * You gather the **Coins** that spent, 29 | * You gather the **Keys** that you own, 30 | * You enumerate how much **Money** you want to send to what **scriptPubKey**, 31 | * You build and sign the **transaction**, 32 | * **Optional**: you give the **transaction** to somebody else, then he will sign or continue to build it. 33 | 34 | Now let’s gather some **Coins**, for that let us create a fake **transaction** with some funds on it. 35 | Let’s say that the **transaction** has a **P2PKH**, **P2PK**, and **multi-sig** coin of Bob and Alice. 36 | 37 | ```cs 38 | // Create a fake transaction 39 | var bob = new Key(); 40 | var alice = new Key(); 41 | 42 | Script bobAlice = 43 | PayToMultiSigTemplate.Instance.GenerateScriptPubKey( 44 | 2, 45 | bob.PubKey, alice.PubKey); 46 | 47 | var init = new Transaction(); 48 | init.Outputs.Add(new TxOut(Money.Coins(1m), bob.PubKey)); // P2PK 49 | init.Outputs.Add(new TxOut(Money.Coins(1m), alice.PubKey.Hash)); // P2PKH 50 | init.Outputs.Add(new TxOut(Money.Coins(1m), bobAlice)); 51 | ``` 52 | 53 | Now let’s say they want to use the ```coins``` of this transaction to pay Satoshi. 54 | 55 | ```cs 56 | var satoshi = new Key(); 57 | ``` 58 | 59 | First they have to get their **Coins**. 60 | 61 | ```cs 62 | Coin[] coins = init.Outputs.AsCoins().ToArray(); 63 | Coin bobCoin = coins[0]; 64 | Coin aliceCoin = coins[1]; 65 | Coin bobAliceCoin = coins[2]; 66 | ``` 67 | 68 | Now let’s say ```bob``` wants to sends 0.2 Stratis, ```alice``` 0.3 Stratis, and they agree to use ```bobAlice``` to send 0.5 Stratis. 69 | 70 | ```cs 71 | var builder = new TransactionBuilder(); 72 | Transaction tx = builder 73 | .AddCoins(bobCoin) 74 | .AddKeys(bob) 75 | .Send(satoshi, Money.Coins(0.2m)) 76 | .SetChange(bob) 77 | .Then() 78 | .AddCoins(aliceCoin) 79 | .AddKeys(alice) 80 | .Send(satoshi, Money.Coins(0.3m)) 81 | .SetChange(alice) 82 | .Then() 83 | .AddCoins(bobAliceCoin) 84 | .AddKeys(bob, alice) 85 | .Send(satoshi, Money.Coins(0.5m)) 86 | .SetChange(bobAlice) 87 | .SendFees(Money.Coins(0.0001m)) 88 | .BuildTransaction(sign: true); 89 | ``` 90 | 91 | Then you can verify it is fully signed and ready to send to the network. 92 | 93 | ```cs 94 | Console.WriteLine(builder.Verify(tx)); // True 95 | ``` 96 | 97 | The nice thing about this model is that it works the same way for **P2SH, P2WSH, P2SH(P2WSH)**, and **P2SH(P2PKH)** except you need to create **ScriptCoin**. 98 | 99 | ![](../assets/ScriptCoinFromCoin.png) 100 | 101 | ```cs 102 | init = new Transaction(); 103 | init.Outputs.Add(new TxOut(Money.Coins(1.0m), bobAlice.Hash)); 104 | 105 | coins = init.Outputs.AsCoins().ToArray(); 106 | ScriptCoin bobAliceScriptCoin = coins[0].ToScriptCoin(bobAlice); 107 | ``` 108 | 109 | Then the signature: 110 | 111 | ```cs 112 | builder = new TransactionBuilder(); 113 | tx = builder 114 | .AddCoins(bobAliceScriptCoin) 115 | .AddKeys(bob, alice) 116 | .Send(satoshi, Money.Coins(0.9m)) 117 | .SetChange(bobAlice.Hash) 118 | .SendFees(Money.Coins(0.0001m)) 119 | .BuildTransaction(true); 120 | Console.WriteLine(builder.Verify(tx)); // True 121 | ``` 122 | 123 | For **Stealth Coin**, this is basically the same thing. Except that, if you remember our introduction on Dark Wallet, I said that you need a **ScanKey** to see the **StealthCoin**. 124 | 125 | ![](../assets/StealthCoin.png) 126 | 127 | Let’s create darkAliceBob stealth address as in previous chapter: 128 | 129 | ```cs 130 | Key scanKey = new Key(); 131 | StratisStealthAddress darkAliceBob = 132 | new StratisStealthAddress 133 | ( 134 | scanKey: scanKey.PubKey, 135 | pubKeys: new[] { alice.PubKey, bob.PubKey }, 136 | signatureCount: 2, 137 | bitfield: null, 138 | network: Network.Main 139 | ); 140 | ``` 141 | 142 | Let’s say someone sent this transaction: 143 | 144 | ```cs 145 | //Someone sent to darkAliceBob 146 | init = new Transaction(); 147 | darkAliceBob 148 | .SendTo(init, Money.Coins(1.0m)); 149 | ``` 150 | 151 | The scanner will detect the StealthCoin: 152 | 153 | ```cs 154 | //Get the stealth coin with the scanKey 155 | StealthCoin stealthCoin 156 | = StealthCoin.Find(init, darkAliceBob, scanKey); 157 | ``` 158 | 159 | And forward it to bob and alice, who will sign: 160 | 161 | ```cs 162 | //Spend it 163 | tx = builder 164 | .AddCoins(stealthCoin) 165 | .AddKeys(bob, alice, scanKey) 166 | .Send(satoshi, Money.Coins(0.9m)) 167 | .SetChange(bobAlice.Hash) 168 | .SendFees(Money.Coins(0.0001m)) 169 | .BuildTransaction(true); 170 | Console.WriteLine(builder.Verify(tx)); // True 171 | ``` 172 | 173 | > **Note:** You need the scanKey for spending a StealthCoin 174 | -------------------------------------------------------------------------------- /second_communitry_edition.md: -------------------------------------------------------------------------------- 1 | # Second (Community) Edition {#second-community-edition} 2 | 3 | ([nopara73](https://github.com/nopara73)) I got sucked into Bitcoin in 2013. At the time everyone was talking about the countless great opportunities for developers, but I was not able to catch any of them. 4 | Every time I tried to do any coding, I encountered countless walls, countless missing pieces and tremendous amount of work that is needed to be done before I could even start working on my idea. 5 | 6 | A few years later I have pleasantly noticed someone has already done the work I talked about. 7 | Someone has finally broken down the crypto voodoo into object oriented niceness. My excitement has further grown when I realized Nicolas Dorier's C# library is the biggest, most complete Bitcoin library out there and it is working on every platform. More, he even wrote a book around it! So now I have the chance to work with the most powerful, best documented Bitcoin library up to date in my favorite programming language. 8 | 9 | But my excitement, Bitcoin addiction and risk-taking personality did not let me stop here. I contacted Nicolas, and long story short, a month ago I found myself on a plane, flying to Tokyo to fully devote myself to Bitcoin, learning under the guidance of Nicolas until my savings run out and I have to find a job. 10 | So far it resulted in the second edition of this book, and a very messy room, since I was not able to find time to unpack my luggage. What is more astonishing by knowing I am a neat-freak. 11 | 12 | Oh, yes... the book. Compared to the first edition, I have updated it by introducing Nicolas' latest works, fixed a bunch of typos (and left just as much), extended it in many places in order to make it understandable by humans and last but not least I have ported all of it to GitHub / Gitbook, so now the community itself will be able to get involved to the book development. 13 | 14 | 15 | If I had to describe the book in one sentence it would be this one: **Let's not talk Bitcoin, let's do Bitcoin!** 16 | --------------------------------------------------------------------------------