├── sha256 ├── transactions.txt ├── NOTES.md ├── README.md ├── hashrate.go └── hash.go ├── i ├── tulipmania.png ├── xkcd1597.png ├── trolly-ponzi.png ├── cryptokitties.png ├── libra-shrugged.png ├── tulipmania-ii.png ├── blockchain-jesus.png ├── cryptokitties-genes01.png ├── cryptokitties-top10-sales.png ├── fake-dilbert-blockchain.png ├── cryptokitties-modernart-paintings.png └── cryptokitties-modernart-paintings-iii.png ├── blockchain.js ├── .gitignore ├── package.json ├── README.md ├── blockchain.js └── blockchain_with_proof_of_work.js ├── blockchain.rs ├── src │ ├── hashable.rs │ ├── block.rs │ ├── transaction.rs │ ├── lib.rs │ ├── main.rs │ └── blockchain.rs ├── Cargo.toml └── README.md ├── blockchain.go ├── README.md ├── blockchain.go └── blockchain_with_proof_of_work.go ├── blockchain.py ├── README.md ├── blockchain.py └── blockchain_with_proof_of_work.py ├── merkletree.rb ├── README.md └── merkletree.rb ├── blockchain.kt ├── README.md ├── blockchain.kts └── blockchain-with-proof-of-work.kts ├── PROOFS.md ├── blockchain.rb ├── README.md ├── blockchain.rb ├── blockchain_with_proof_of_work.rb └── blockchain_with_transactions.rb ├── NOTES.md ├── HASH.md ├── blockchain.cpp ├── blockchain.cpp └── blockchain_with_proof_of_work.cpp ├── TULIPS.md ├── WHATSBLOCKCHAIN.md ├── LICENSE.md └── README.md /sha256/transactions.txt: -------------------------------------------------------------------------------- 1 | from: alice, to: bob, $100 2 | from: teresa, to: josef, $111 3 | -------------------------------------------------------------------------------- /i/tulipmania.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openblockchains/awesome-blockchains/HEAD/i/tulipmania.png -------------------------------------------------------------------------------- /i/xkcd1597.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openblockchains/awesome-blockchains/HEAD/i/xkcd1597.png -------------------------------------------------------------------------------- /i/trolly-ponzi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openblockchains/awesome-blockchains/HEAD/i/trolly-ponzi.png -------------------------------------------------------------------------------- /i/cryptokitties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openblockchains/awesome-blockchains/HEAD/i/cryptokitties.png -------------------------------------------------------------------------------- /i/libra-shrugged.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openblockchains/awesome-blockchains/HEAD/i/libra-shrugged.png -------------------------------------------------------------------------------- /i/tulipmania-ii.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openblockchains/awesome-blockchains/HEAD/i/tulipmania-ii.png -------------------------------------------------------------------------------- /blockchain.js/.gitignore: -------------------------------------------------------------------------------- 1 | ### 2 | # ignore npm / node modules 3 | 4 | node_modules/ 5 | package-lock.json 6 | -------------------------------------------------------------------------------- /i/blockchain-jesus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openblockchains/awesome-blockchains/HEAD/i/blockchain-jesus.png -------------------------------------------------------------------------------- /i/cryptokitties-genes01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openblockchains/awesome-blockchains/HEAD/i/cryptokitties-genes01.png -------------------------------------------------------------------------------- /i/cryptokitties-top10-sales.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openblockchains/awesome-blockchains/HEAD/i/cryptokitties-top10-sales.png -------------------------------------------------------------------------------- /i/fake-dilbert-blockchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openblockchains/awesome-blockchains/HEAD/i/fake-dilbert-blockchain.png -------------------------------------------------------------------------------- /i/cryptokitties-modernart-paintings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openblockchains/awesome-blockchains/HEAD/i/cryptokitties-modernart-paintings.png -------------------------------------------------------------------------------- /i/cryptokitties-modernart-paintings-iii.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openblockchains/awesome-blockchains/HEAD/i/cryptokitties-modernart-paintings-iii.png -------------------------------------------------------------------------------- /blockchain.js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blockchain.js", 3 | "version": "1.0.0", 4 | "main": "blockchain.js", 5 | "license": "Public Domain", 6 | "dependencies": { 7 | "js-sha256": "^0.6.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /blockchain.rs/src/hashable.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | pub trait Hashable { 4 | fn bytes(&self) -> Vec ; 5 | 6 | fn hash(&self) -> Hash { 7 | crypto_hash::digest(crypto_hash::Algorithm::SHA256, &self.bytes()) 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /blockchain.go/README.md: -------------------------------------------------------------------------------- 1 | # blockchain.go - Build your own blockchain from scratch in go(lang) 2 | 3 | 4 | **Starter (Version)** 5 | 6 | to run use: 7 | 8 | $ go run blockchain.go 9 | 10 | 11 | **Proof of Work (Version)** 12 | 13 | to run use: 14 | 15 | $ go run blockchain_with_proof_of_work.go 16 | -------------------------------------------------------------------------------- /sha256/NOTES.md: -------------------------------------------------------------------------------- 1 | # Notes 2 | 3 | 4 | ## Online Hash Calculators / Converters 5 | 6 | 7 | 8 | 9 | ## Todos 10 | 11 | Add section / example for: 12 | 13 | - what's your hash rate? 14 | - proof-of-work / hashcash 15 | - double hash (like used in bitcoin) 16 | - bitcoin block header hash from genesis 17 | - ???? 18 | 19 | 20 | More languages: 21 | 22 | - add javascript ?? 23 | - add rust ?? 24 | -------------------------------------------------------------------------------- /blockchain.rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "too_chainz" 3 | version = "0.1.0" 4 | authors = ["Siddhant "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [lib] 10 | name = "blockchainlib" 11 | path = "src/lib.rs" 12 | 13 | [[bin]] 14 | name = "main" 15 | path = "src/main.rs" 16 | 17 | [dependencies] 18 | hex = "0.3.2" 19 | crypto-hash = "0.3.3" -------------------------------------------------------------------------------- /blockchain.py/README.md: -------------------------------------------------------------------------------- 1 | # blockchain.py - Build your own blockchain from scratch in python3 2 | 3 | inspired by 4 | [Let's Build the Tiniest Blockchain In Less Than 50 Lines of Python](https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b) 5 | by Gerald Nash 6 | 7 | 8 | **Starter (Version)** 9 | 10 | to run use: 11 | 12 | $ python ./blockchain.py 13 | 14 | 15 | **Proof of Work (Version)** 16 | 17 | to run use: 18 | 19 | $ python ./blockchain_with_proof_of_work.py 20 | -------------------------------------------------------------------------------- /merkletree.rb/README.md: -------------------------------------------------------------------------------- 1 | # merkletree.rb - Calc(ulate) your own merkle tree hash from scratch in ruby 2 | 3 | inspired by [building a merkle tree (in c++)](https://github.com/bitcoinbook/bitcoinbook/blob/second_edition/ch09.asciidoc#merkle-trees) - 4 | [(merkle.cpp)](https://github.com/bitcoinbook/bitcoinbook/blob/second_edition/code/merkle.cpp) in the book "Mastering Bitcoin - Programming the Open Blockchain" by Andreas M. Antonopoulos 5 | 6 | **Starter (Version)** 7 | 8 | to run use: 9 | 10 | $ ruby ./merkletree.rb 11 | 12 | -------------------------------------------------------------------------------- /blockchain.js/README.md: -------------------------------------------------------------------------------- 1 | # blockchain.js - Build your own blockchain from scratch in 20 lines of javascript 2 | 3 | inspired by 4 | [Let's Build the Tiniest Blockchain In Less Than 50 Lines of Python](https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b) 5 | by Gerald Nash 6 | 7 | 8 | One time install: 9 | 10 | $ npm install -- or npm install -g js-sha256 11 | 12 | 13 | **Starter (Version)** 14 | 15 | to run use: 16 | 17 | $ node ./blockchain.js 18 | 19 | 20 | **Proof of Work (Version)** 21 | 22 | to run use: 23 | 24 | $ node ./blockchain_with_proof_of_work.js 25 | -------------------------------------------------------------------------------- /blockchain.rs/README.md: -------------------------------------------------------------------------------- 1 | # blockchain.rs - Build your own blockchain from scratch in Rust 2 | 3 | inspired by [Build a cryptocurrency! - Blockchain in Rust](https://github.com/GeekLaunch/blockchain-rust) by Jacob Lindahl, GeekLaunch 4 | 5 | 6 | contributed by [Siddhant Rao](https://github.com/siddhantrao23) 7 | 8 | 9 | 10 | Structure definition: 11 | 12 | ``` rust 13 | pub struct Block { 14 | pub index: u32, 15 | pub timestamp: u128, 16 | pub hash: Hash, 17 | pub prev_block_hash: Hash, 18 | pub nonce: u64, 19 | pub transactions: Vec, 20 | pub difficulty: u128, 21 | } 22 | ``` 23 | 24 | 25 | To run use: 26 | 27 | $ cargo run 28 | 29 | 30 | 31 | 32 | ## Sources 33 | 34 | See [`too_chainz`](https://github.com/siddhantrao23/too_chainz). 35 | -------------------------------------------------------------------------------- /blockchain.kt/README.md: -------------------------------------------------------------------------------- 1 | # blockchain.kt - Build your own blockchain from scratch in 20 lines of Kotlin 2 | 3 | contributed by [B. K. Oxley (binkley)](https://github.com/binkley) 4 | 5 | 6 | **Starter (Version)** 7 | 8 | to run use: 9 | 10 | $ kotlinc-jvm -script ./blockchain.kts 11 | 12 | 13 | **Proof of Work (Version)** 14 | 15 | to run use: 16 | 17 | $ kotlinc-jvm -script ./blockchain-with-proof-of-work.kts 18 | 19 | 20 | 21 | 22 | ## Bonus 23 | 24 | B. K. Oxley (binkley) writes: 25 | 26 | After a series of emails with a CS prof friend of mine, I've made a more sophisticated Kotlin version of blockchain. My last challenge is to produce a true Merkle tree (forthcoming), see 27 | 28 | - 29 | -------------------------------------------------------------------------------- /PROOFS.md: -------------------------------------------------------------------------------- 1 | Proofs for Finding Consensus • Proofs for Finding Truth • Consensus Protocols 2 | 3 | 4 | # Awesome Proofs 5 | 6 | A curated list of proofs for finding consensus / for finding truth. 7 | 8 | 9 | ## Proof of Work / Proof of Waste (PoW) 10 | 11 | Using a lottery to pick the winner - to "play" you have to "work" - the more you "work" the bigger your chances to win. 12 | 13 | 14 | ## Proof of Stake (PoS) 15 | 16 | 17 | ## Proof of Authority (PoA) 18 | 19 | ## Proof of Person / Proof of Personhood (PoP) 20 | 21 | 22 | ## Proof of Importance (PoI) 23 | 24 | ## Proof of Activity (PoA) 25 | 26 | 27 | ## Proof of Burn 28 | 29 | 30 | ## Proof of Capacity 31 | 32 | 33 | ### Proof of Storage 34 | 35 | ### Proof of Space 36 | 37 | 38 | 39 | ## Proof of Elapsed Time (PoET) 40 | 41 | Invented By Chipmaker Intel. 42 | The algorithm uses a trusted execution environment (TEE) 43 | to ensure blocks get produced in a random lottery fashion, but without the required work. 44 | 45 | 46 | 47 | ## Proof of Pudding (PoP) 48 | 49 | Proverb - "You can only say something is a success after it has been tried out or used." 50 | 51 | 52 | 53 | ## Notes 54 | 55 | [A (Short) Guide to Blockchain Consensus Protocols @ CoinDesk](https://www.coindesk.com/short-guide-blockchain-consensus-protocols/), 56 | Mar 2017 at 11:50 UTC by Amy Castor 57 | 58 | 59 | -------------------------------------------------------------------------------- /blockchain.rs/src/block.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use std::fmt::{ self, Debug, Formatter }; 3 | 4 | pub struct Block { 5 | pub index: u32, 6 | pub timestamp: u128, 7 | pub hash: Hash, 8 | pub prev_block_hash: Hash, 9 | pub nonce: u64, 10 | pub transactions: Vec, 11 | pub difficulty: u128, 12 | } 13 | 14 | impl Debug for Block { 15 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { 16 | write!(f, "Block[{}]: {} at: {} with: nonce:{}\n", 17 | &self.index, 18 | &hex::encode(&self.hash), 19 | &self.timestamp, 20 | &self.nonce, 21 | ) 22 | } 23 | } 24 | 25 | impl Block { 26 | pub fn new(index:u32, timestamp:u128, prev_block_hash:Hash, 27 | transactions: Vec, difficulty: u128) -> Self { 28 | Block { 29 | index, 30 | timestamp, 31 | hash: vec![0; 32], 32 | prev_block_hash, 33 | nonce: 0, 34 | transactions, 35 | difficulty, 36 | } 37 | } 38 | 39 | pub fn mine(&mut self) { 40 | for nonce_attempt in 0..(u64::max_value()) { 41 | self.nonce = nonce_attempt; 42 | let hash = self.hash(); 43 | if check_difficulty(&hash, self.difficulty) { 44 | self.hash = hash; 45 | return; 46 | } 47 | } 48 | } 49 | } 50 | 51 | impl Hashable for Block { 52 | fn bytes(&self) -> Vec { 53 | let mut bytes = vec![]; 54 | 55 | bytes.extend(&u32_bytes(&self.index)); 56 | bytes.extend(&u128_bytes(&self.timestamp)); 57 | bytes.extend(&self.prev_block_hash); 58 | bytes.extend(&u64_bytes(&self.nonce)); 59 | bytes.extend( 60 | self.transactions 61 | .iter() 62 | .flat_map(|transaction| transaction.bytes()) 63 | .collect::>() 64 | ); 65 | bytes.extend(&u128_bytes(&self.difficulty)); 66 | 67 | bytes 68 | } 69 | } 70 | 71 | pub fn check_difficulty(hash: &Hash, difficulty: u128) -> bool { 72 | difficulty > difficulty_bytes_as_u128(&hash) 73 | } 74 | 75 | -------------------------------------------------------------------------------- /blockchain.rs/src/transaction.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use std::collections::HashSet; 3 | 4 | #[derive(Clone)] 5 | pub struct Output { 6 | pub to_addr: Address, 7 | pub value: u64, 8 | } 9 | 10 | impl Hashable for Output { 11 | fn bytes(&self) -> Vec { 12 | let mut bytes = vec![]; 13 | 14 | bytes.extend(self.to_addr.as_bytes()); 15 | bytes.extend(&u64_bytes(&self.value)); 16 | 17 | bytes 18 | } 19 | } 20 | 21 | pub struct Transaction { 22 | pub inputs: Vec, 23 | pub outputs: Vec, 24 | } 25 | 26 | impl Transaction { 27 | pub fn input_value(&self) -> u64 { 28 | self.inputs 29 | .iter() 30 | .map(|input| input.value) 31 | .sum() 32 | } 33 | 34 | pub fn output_value(&self) -> u64 { 35 | self.outputs 36 | .iter() 37 | .map(|output| output.value) 38 | .sum() 39 | } 40 | 41 | pub fn input_hashes(&self) -> HashSet { 42 | self.inputs 43 | .iter() 44 | .map(|input| input.hash()) 45 | .collect::>() 46 | } 47 | 48 | pub fn output_hashes(&self) -> HashSet { 49 | self.outputs 50 | .iter() 51 | .map(|output| output.hash()) 52 | .collect::>() 53 | } 54 | 55 | pub fn is_coinbase(&self) -> bool { 56 | self.inputs.len() == 0 57 | } 58 | } 59 | 60 | impl Hashable for Transaction { 61 | fn bytes(&self) -> Vec { 62 | let mut bytes = vec![]; 63 | 64 | bytes.extend( 65 | self.inputs 66 | .iter() 67 | .flat_map(|inputs| inputs.bytes()) 68 | .collect::>() 69 | ); 70 | 71 | bytes.extend( 72 | self.outputs 73 | .iter() 74 | .flat_map(|output| output.bytes()) 75 | .collect::>() 76 | ); 77 | 78 | bytes 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /blockchain.rb/README.md: -------------------------------------------------------------------------------- 1 | # blockchain.rb - Build your own blockchain from scratch in 20 lines of ruby 2 | 3 | inspired by 4 | [Let's Build the Tiniest Blockchain In Less Than 50 Lines of Python](https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b) 5 | by Gerald Nash 6 | 7 | 8 | **Starter (Version)** 9 | 10 | to run use: 11 | 12 | $ ruby ./blockchain.rb 13 | 14 | 15 | **Proof of Work (Version)** 16 | 17 | to run use: 18 | 19 | $ ruby ./blockchain_with_proof_of_work.rb 20 | 21 | 22 | **Transactions (Version)** 23 | 24 | to run use: 25 | 26 | $ ruby ./blockchain_with_transactions.rb 27 | 28 | 29 | 30 | 31 | ## Questions? Comments? 32 | 33 | From the [reddit ruby posting](https://www.reddit.com/r/ruby/comments/70c30f/build_your_own_blockchain_in_20_lines_of_ruby/): 34 | 35 | > Wait, so a blockchain is just a linked list? 36 | > 37 | >> No. A linked list is only required to have a reference to the previous element, a block must 38 | >> have an identifier depending on the previous block's identifier, meaning that you cannot 39 | >> replace a block without recomputing every single block that comes after. 40 | >> In this implementation that happens as the previous digest is input in the calc_hash method. 41 | 42 | --- 43 | 44 | > This is a "blockchain" in only the most literal sense of the word. 45 | > 46 | >> That's the best sense of the word. 47 | >> 48 | >>> No, this ruby class misses the whole point... 49 | >>> a distributed data structure built by independent actors all putting in real work 50 | >>> and receiving rewards for successfully solving the next block. 51 | >>> 52 | >>>> While you're on to the fact that blockchain is not quite as interesting without proof of 53 | >>>> work, those are two totally independent concepts, and one is not needed to illustrate the 54 | >>>> other. 55 | 56 | 57 | 58 | ## Alternatives 59 | 60 | [blockchain.rb](https://github.com/MatiasFMolinari/blockchain-ruby) by Matias Fernandez -- It's 8 lines, but that's because I removed the class methods. 61 | -------------------------------------------------------------------------------- /sha256/README.md: -------------------------------------------------------------------------------- 1 | # Awesome SHA256 2 | 3 | A collection about the most awesome crypto (one-way) hash function / digest / fingerprint - Secure Hash Algorithm 256-Bit (SHA256) 4 | 5 | 6 | 7 | Trivia Quiz: What's SHA256? 8 | 9 | - (A) Still Hacking Anyway 10 | - (B) Secure Hash Algorithm 11 | - (C) Sweet Home Austria 12 | - (D) Super High Aperture 13 | 14 | A: SHA256 == Secure Hash Algorithm 256-Bit 15 | 16 | SHA256 is a (secure) hashing algorithm designed 17 | by the National Security Agency (NSA) of the United States of America (USA). 18 | 19 | Find out more @ [Secure Hash Algorithms (SHA) @ Wikipedia](https://en.wikipedia.org/wiki/Secure_Hash_Algorithms). 20 | 21 | A (secure) hash is also known as: 22 | 23 | - Digital (Crypto) Fingerprint == (Secure) Hash 24 | - Digital (Crypto) Digest == (Secure) Hash 25 | - Digital (Crypto) Checksum == (Secure) Hash 26 | 27 | 28 | 29 | ## Hello, Cryptos! 30 | 31 | Print the SHA256 hash digest as a 64 hex string for "Hello, Cryptos!" 32 | 33 | Note: 1 hex char is 4-bits, 2 hex chars are 4x2=8 bits 34 | and 64 hex chars are 4x64=256 bits. 35 | 36 | Hexa(decimal) chart: 37 | 38 | |binary|hex (2^4=16)|decimal|binary|hex (2^4=16)|decimal| 39 | |------|------------|-------|------|------------|-------| 40 | | 0000 | **0** | 0 | 1000 | **8** | 8 | 41 | | 0001 | **1** | 1 | 1001 | **9** | 9 | 42 | | 0010 | **2** | 2 | 1010 | **a** | 10 | 43 | | 0011 | **3** | 3 | 1011 | **b** | 11 | 44 | | 0100 | **4** | 4 | 1100 | **c** | 12 | 45 | | 0101 | **5** | 5 | 1101 | **d** | 13 | 46 | | 0110 | **6** | 6 | 1110 | **e** | 14 | 47 | | 0111 | **7** | 7 | 1111 | **f** | 15 | 48 | 49 | 50 | ### Ruby 51 | 52 | ``` ruby 53 | require "digest" 54 | 55 | p Digest::SHA256.hexdigest( "Hello, Cryptos!" ) 56 | # => 33eedea60b0662c66c289ceba71863a864cf84b00e10002ca1069bf58f9362d 57 | ``` 58 | 59 | ### Go 60 | 61 | ``` go 62 | package main 63 | 64 | import( 65 | "fmt" 66 | "crypto/sha256" 67 | ) 68 | 69 | func main() { 70 | fmt.Printf( "%x\n", sha256.Sum256( []byte( "Hello, Cryptos!" ))) 71 | // => 33eedea60b0662c66c289ceba71863a864cf84b00e10002ca1069bf58f9362d5 72 | } 73 | ``` 74 | 75 | 76 | -------------------------------------------------------------------------------- /blockchain.kt/blockchain.kts: -------------------------------------------------------------------------------- 1 | import java.security.MessageDigest 2 | import java.time.Instant 3 | 4 | class Block( 5 | val index: Int, 6 | val data: Any, 7 | val previousHash: String 8 | ) { 9 | val timestamp = Instant.now() 10 | val hash = calcHash() 11 | 12 | fun next(data: Any) = Block(index + 1, data, hash) 13 | 14 | private fun calcHash() = sha256 15 | .digest("$index$timestamp$data$previousHash".toByteArray()) 16 | .joinToString("") { "%02x".format(it) } 17 | 18 | override fun toString(): String { 19 | return "Block(data=$data, hash=$hash, index=$index, previousHash=$previousHash, timestamp=$timestamp)" 20 | } 21 | 22 | companion object { 23 | private val sha256 = MessageDigest.getInstance("SHA-256") 24 | 25 | fun first(data: Any = "Genesis") = Block(0, data, "0") 26 | } 27 | } 28 | 29 | /* 30 | * Will pretty print (without line wrapping) something like: 31 | * ``` 32 | * [Block(data=Genesis, 33 | * hash=8145610a47769c76136d0c844d1e88d9782e1d8bfcae74314e472ca0ac25d684, 34 | * index=0, 35 | * previousHash=0, 36 | * timestamp=2019-12-29T16:17:21.805435Z), 37 | * Block(data=Transaction Data..., 38 | * hash=08b138384bc2645272de76a060b19d2b2dee8d87208a872bfd859b9fe9333370, 39 | * index=1, 40 | * previousHash=8145610a47769c76136d0c844d1e88d9782e1d8bfcae74314e472ca0ac25d684, 41 | * timestamp=2019-12-29T16:17:21.837617Z), 42 | * Block(data=Transaction Data......, 43 | * hash=1cce7b717ca1409cbded1d9dd7d2475dd99de515676d2842b1e2592324772053, 44 | * index=2, 45 | * previousHash=08b138384bc2645272de76a060b19d2b2dee8d87208a872bfd859b9fe9333370, 46 | * timestamp=2019-12-29T16:17:21.838652Z), 47 | * Block(data=More Transaction Data..., 48 | * hash=e5723ab31156e91d27db8ad4441a29f3ecfd9cda3e91284bd5d583bed8e91212, 49 | * index=3, 50 | * previousHash=1cce7b717ca1409cbded1d9dd7d2475dd99de515676d2842b1e2592324772053, 51 | * timestamp=2019-12-29T16:17:21.839509Z)] 52 | * ``` 53 | */ 54 | 55 | val b0 = Block.first("Genesis") 56 | val b1 = b0.next("Transaction Data...") 57 | val b2 = b1.next("Transaction Data......") 58 | val b3 = b2.next("More Transaction Data...") 59 | 60 | val blockchain = listOf(b0, b1, b2, b3) 61 | 62 | println(blockchain) 63 | -------------------------------------------------------------------------------- /blockchain.rs/src/lib.rs: -------------------------------------------------------------------------------- 1 | type Hash = Vec; 2 | type Address = String; 3 | 4 | use std::time::{ SystemTime, UNIX_EPOCH }; 5 | 6 | pub fn now () -> u128 { 7 | let duration = SystemTime::now() 8 | .duration_since(UNIX_EPOCH) 9 | .unwrap() 10 | ; 11 | 12 | duration.as_secs() as u128 * 1000 + duration.subsec_millis() as u128 13 | } 14 | 15 | pub fn u32_bytes (u: &u32) -> [u8; 4] { 16 | [ 17 | (u >> 8 * 0x0) as u8, 18 | (u >> 8 * 0x1) as u8, 19 | (u >> 8 * 0x2) as u8, 20 | (u >> 8 * 0x3) as u8, 21 | ] 22 | } 23 | 24 | pub fn u64_bytes (u: &u64) -> [u8; 8] { 25 | [ 26 | (u >> 8 * 0x0) as u8, 27 | (u >> 8 * 0x1) as u8, 28 | (u >> 8 * 0x2) as u8, 29 | (u >> 8 * 0x3) as u8, 30 | 31 | (u >> 8 * 0x4) as u8, 32 | (u >> 8 * 0x5) as u8, 33 | (u >> 8 * 0x6) as u8, 34 | (u >> 8 * 0x7) as u8, 35 | ] 36 | } 37 | 38 | pub fn u128_bytes (u: &u128) -> [u8; 16] { 39 | [ 40 | (u >> 8 * 0x0) as u8, 41 | (u >> 8 * 0x1) as u8, 42 | (u >> 8 * 0x2) as u8, 43 | (u >> 8 * 0x3) as u8, 44 | 45 | (u >> 8 * 0x4) as u8, 46 | (u >> 8 * 0x5) as u8, 47 | (u >> 8 * 0x6) as u8, 48 | (u >> 8 * 0x7) as u8, 49 | 50 | (u >> 8 * 0x8) as u8, 51 | (u >> 8 * 0x9) as u8, 52 | (u >> 8 * 0xa) as u8, 53 | (u >> 8 * 0xb) as u8, 54 | 55 | (u >> 8 * 0xc) as u8, 56 | (u >> 8 * 0xd) as u8, 57 | (u >> 8 * 0xe) as u8, 58 | (u >> 8 * 0xf) as u8, 59 | ] 60 | } 61 | 62 | pub fn difficulty_bytes_as_u128 (v: &Vec) -> u128 { 63 | ((v[31] as u128) << 0xf * 8) | 64 | ((v[30] as u128) << 0xe * 8) | 65 | ((v[29] as u128) << 0xd * 8) | 66 | ((v[28] as u128) << 0xc * 8) | 67 | ((v[27] as u128) << 0xb * 8) | 68 | ((v[26] as u128) << 0xa * 8) | 69 | ((v[25] as u128) << 0x9 * 8) | 70 | ((v[24] as u128) << 0x8 * 8) | 71 | ((v[23] as u128) << 0x7 * 8) | 72 | ((v[22] as u128) << 0x6 * 8) | 73 | ((v[21] as u128) << 0x5 * 8) | 74 | ((v[20] as u128) << 0x4 * 8) | 75 | ((v[19] as u128) << 0x3 * 8) | 76 | ((v[18] as u128) << 0x2 * 8) | 77 | ((v[17] as u128) << 0x1 * 8) | 78 | ((v[16] as u128) << 0x0 * 8) 79 | } 80 | 81 | mod block; 82 | pub use crate::block::Block; 83 | mod hashable; 84 | pub use crate::hashable::Hashable; 85 | mod blockchain; 86 | pub use crate::blockchain::Blockchain; 87 | pub mod transaction; 88 | pub use crate::transaction::Transaction; 89 | 90 | -------------------------------------------------------------------------------- /NOTES.md: -------------------------------------------------------------------------------- 1 | # Notes 2 | 3 | 4 | ## Tulip Mania 5 | 6 | [Josua Schmid](https://github.com/schmijos) writes: 7 | 8 | Interesting for the context is that blockchain ETFs just started in November 2017. 9 | 10 | **Notice:** The tulip bubble was about future contracts (which specified cancellation fines) and never about the price of a tulip. Tulips are planted in autumn. They were underground while the mania happened. Often financial derivaties make bubbles and not the market per se. 11 | 12 | 13 | 14 | 15 | ## How many blocks? 16 | 17 | - xx blocks / week, / month, / year 18 | - a block every 20 minutes (a block every hour) 19 | 20 | 21 | ## Blockchains Samples 22 | 23 | Add - why? why not? 24 | 25 | - Bitcoin (started in ) - blocks/year - blocks in 1.1.2017, in 1.1.2018 26 | - Bitcoin Forks 27 | - Bitcoin Cash (Blockchain) 28 | - Bitcoin XL (Blockchain) 29 | - ... 30 | 31 | Bitcoin Block Header - 80 bytes 32 | includes: 33 | - timestamp (in unix epoch time - (mili?)seconds since 1970 - unsigned int for 2023 problem/overflow) 34 | - merkle_tree_hash (transactions / txs ) - SHA512 ?? 35 | 36 | 37 | 38 | ## More Questions 39 | 40 | - Q: What's a Sidechain? 41 | - Q: What's a Hyper Ledger Book? 42 | 43 | 44 | ## Blockchain in Austria 45 | 46 | Add AUSTRIA.md page? 47 | 48 | - Blockchain Austria (Bundesministerium f. Wirtschaft) 49 | - Bundesrechenzentrum 50 | - Stadt Wien 51 | 52 | 53 | ## Blockchain - Data Structure vs Network 54 | 55 | How many (network) nodes? 56 | 57 | 58 | ## More Build Your Own Blockchain Samples / Projects 59 | 60 | ### Python 61 | 62 | **Dumbcoin** - An educational python implementation of a bitcoin-like blockchain 63 | - https://github.com/julienr/ipynb_playground/blob/master/bitcoin/dumbcoin/dumbcoin.ipynb 64 | 65 | Tiniest Blockchain in Python Article (Alternatives): 66 | 67 | - https://gist.github.com/aunyks/8f2c2fd51cc17f342737917e1c2582e2 68 | - https://gist.github.com/thinkholic/35f3b4bdcd107d0bc088b6681e39e414 69 | 70 | 71 | ### Ruby 72 | 73 | blockchain.rb Ruby Alternatives: 74 | 75 | - https://github.com/MatiasFMolinari/blockchain-ruby/blob/master/blockchain.rb Less than 10 Lines! 76 | 77 | 78 | ### JavaScript 79 | 80 | **NaiveChain** github: [lhartikk/naivechain](https://github.com/lhartikk/naivechain) -- A blockchain implementation in 200 lines of code (in JavaScript). 81 | 82 | - https://medium.com/@lhartikk/a-blockchain-in-200-lines-of-code-963cc1cc0e54 83 | 84 | 85 | 86 | ### Uncategorized / More 87 | 88 | 89 | **SharpChain** github: [ZenXChaos/SharpChain](https://github.com/ZenXChaos/SharpChain) -- Lite version of the Blockchain. C# Data integrity. 90 | 91 | 92 | -------------------------------------------------------------------------------- /HASH.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # (Crypto) Hash 4 | 5 | Synonyms (also known as): 6 | 7 | - Digital Fingerprint 8 | - Digital Digest 9 | - Digital Checksum 10 | 11 | 12 | 13 | ## SHA256 - Secure Hash Algorithm 256-Bits 14 | 15 | ``` ruby 16 | Digest::SHA256.hexdigest( 'Hello, World!' ) 17 | #=> "dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f" 18 | 19 | Digest::SHA256.hexdigest( 'Hello, World! - Hello, World! - Hello, World! - Hello, World! - Hello, World!' ) 20 | #=> "9e513dbdfe60a14f0cac37aeacbe24fa961b428e8ddeb4d6a66006b29425bbd2" 21 | ``` 22 | 23 | note: 1 hex digit (0-9a-f) = 4 bits; 2 hex digits = 1 byte = 8 bits; 24 | always 64 hex digits (0-9a-f) = 32x8 bytes = 256 bits 25 | 26 | 27 | convert from hex (base 16) to decimal number (base 10) 28 | 29 | ``` ruby 30 | hex = Digest::SHA256.hexdigest( 'Hello, World!' ) 31 | #=> "dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f" 32 | 33 | hex.to_i( 16 ) 34 | #=> 101313441018496298855616188252934726526525012911655317211406949275718146758767 35 | ``` 36 | 37 | convert to 256-bits (32-bytes) binary number (base 2) 38 | 39 | ``` ruby 40 | h.to_i( 16 ).to_s( 2 ) 41 | # => "1101 1111 1111 1101 0110 0000 0010 0001 1011 1011 0010 1011 1101 0101 1011 0000 42 | # 1010 1111 0110 0111 0110 0010 1001 0000 1000 0000 1001 1110 1100 0011 1010 0101 43 | # 0011 0001 1001 0001 1101 1101 1000 0001 1100 0111 1111 0111 0000 1010 0100 1011 44 | # 0010 1000 0110 1000 1000 1010 0011 0110 0010 0001 1000 0010 1001 1000 0110 1111" 45 | ``` 46 | 47 | double check (32x8 bytes = 256 bits): 48 | 49 | | # | bin | hex | # | bin | hex | # | bin | hex | # | bin | hex | 50 | |----|-----------|-----|----|-----------|-----|-----|-----------|-----|-----|-----------|-----| 51 | | 1 | 1101 1111 | d f | 9 | 1010 1111 | a f | 17 | 0011 0001 | 3 1 | 25 | 0010 1000 | 2 8 | 52 | | 2 | 1111 1101 | f d | 10 | 0110 0111 | 6 7 | 18 | 1001 0001 | 9 1 | 26 | 0110 1000 | 6 8 | 53 | | 3 | 0110 0000 | 6 0 | 11 | 0110 0010 | 6 2 | 19 | 1101 1101 | d d | 27 | 1000 1010 | 8 a | 54 | | 4 | 0010 0001 | 2 1 | 12 | 1001 0000 | 9 0 | 20 | 1000 0001 | 8 1 | 28 | 0011 0110 | 3 6 | 55 | | 5 | 1011 1011 | b b | 13 | 1000 0000 | 8 0 | 21 | 1100 0111 | c 7 | 29 | 0010 0001 | 2 1 | 56 | | 6 | 0010 1011 | 2 b | 14 | 1001 1110 | 9 e | 22 | 1111 0111 | f 7 | 30 | 1000 0010 | 8 2 | 57 | | 7 | 1101 0101 | d 5 | 15 | 1100 0011 | c 3 | 23 | 0000 1010 | 0 a | 31 | 1001 1000 | 9 8 | 58 | | 8 | 1011 0000 | b 0 | 16 | 1010 0101 | a 5 | 24 | 0100 1011 | 4 b | 32 | 0110 1111 | 6 f | 59 | 60 | 61 | 62 | Articles: 63 | 64 | - [Secure Hash Algorithms @ Wikipedia](https://en.wikipedia.org/wiki/Secure_Hash_Algorithms) 65 | - [SHA-2 @ Wikipedia](https://en.wikipedia.org/wiki/SHA-2) - Secure Hash Algorithm 2 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /merkletree.rb/merkletree.rb: -------------------------------------------------------------------------------- 1 | ############################################################### 2 | # calc(ulate) your own merkle tree hash from scratch in ruby 3 | # 4 | # inspired by building a merkle tree (in c++) in the book 5 | # Mastering Bitcoin - Programming the Open Blockchain by Andreas M. Antonopoulos 6 | # see https://github.com/bitcoinbook/bitcoinbook/blob/second_edition/ch09.asciidoc#merkle-trees 7 | # https://github.com/bitcoinbook/bitcoinbook/blob/second_edition/code/merkle.cpp 8 | # 9 | # to run use: 10 | # $ ruby ./merkletree.rb 11 | # 12 | # 13 | # todos/check: 14 | # hwo to combine hash pairs? - for now the two hexdigests get joined 15 | 16 | 17 | require "digest" # for hash checksum digest function SHA256 18 | require "pp" # for pp => pretty printer 19 | 20 | 21 | def calc_hash( data ) 22 | sha = Digest::SHA256.new 23 | sha.update( data ) 24 | sha.hexdigest 25 | end 26 | 27 | def compute_merkletree_hash( hashes ) 28 | 29 | if hashes.empty? 30 | return "0" ## return null hash (fix: what's the (proper) null hash?) 31 | elsif hashes.size == 1 32 | return hashes[0] 33 | else 34 | ## while there's more than one hash in the list, keep looping... 35 | while hashes.size > 1 36 | # if number of hashes is odd e.g. 3,5,7,etc., duplicate last hash in list 37 | hashes << hashes[-1] if hashes.size % 2 != 0 38 | 39 | ## new hash list 40 | new_hashes = [] 41 | ## loop through hashes two at a time 42 | hashes.each_slice(2) do |slice| 43 | ## join both hashes slice[0]+slice[1] together 44 | hash = calc_hash( slice[0]+slice[1] ) 45 | new_hashes << hash 46 | end 47 | hashes = new_hashes 48 | 49 | ## debug output 50 | puts "current merkle hash list (#{hashes.size}):" 51 | pp hashes 52 | end 53 | ### finally we end up with a single hash 54 | hashes[0] 55 | end 56 | end # method compute_merkletree_hash 57 | 58 | 59 | hashes = [ 60 | "0000000000000000000000000000000000000000000000000000000000000000", 61 | "0000000000000000000000000000000000000000000000000000000000000011", 62 | "0000000000000000000000000000000000000000000000000000000000000022" 63 | ] 64 | 65 | hash = compute_merkletree_hash( hashes ) 66 | 67 | puts "merkletree hash:" 68 | puts hash 69 | 70 | 71 | ###### 72 | # will print something like: 73 | # 74 | # current merkle hash list (2): 75 | # ["4ff2b6e318d979927a8c780b5e16cf36dc11ee9f95c5f132279d52f21a051520", 76 | # "4d479b4b92c57b9bfcd55f7b674f66f098af8c8de1036b4c419b427c6cd31c83"] 77 | # current merkle hash list (1): 78 | # ["5bffe87c7fd53d98f166661dd6a2d368ba0acc0b5c773d8426f4f153ff23125c"] 79 | # merkletree hash: 80 | # 5bffe87c7fd53d98f166661dd6a2d368ba0acc0b5c773d8426f4f153ff23125c 81 | -------------------------------------------------------------------------------- /blockchain.go/blockchain.go: -------------------------------------------------------------------------------- 1 | ///// 2 | // build your own blockchain from scratch in go(lang) 3 | // 4 | // references: 5 | // - https://jeiwan.cc/posts/building-blockchain-in-go-part-1/ 6 | // - https://jeiwan.cc/posts/building-blockchain-in-go-part-2/ 7 | // - https://medium.com/@mycoralhealth/code-your-own-blockchain-in-less-than-200-lines-of-go-e296282bcffc 8 | // - https://medium.com/@mycoralhealth/code-your-own-blockchain-mining-algorithm-in-go-82c6a71aba1f 9 | // - and (many) others 10 | // 11 | // 12 | // to run use: 13 | // $ go run blockchain.go 14 | 15 | 16 | package main 17 | 18 | import ( 19 | "fmt" 20 | "crypto/sha256" 21 | "encoding/hex" 22 | "time" 23 | "strconv" 24 | ) 25 | 26 | type Block struct { 27 | Time int64 // seconds since (unix) epoch (1970-01-01) 28 | Data string 29 | Prev string // use []byte/int256/uint256 ?? 30 | Hash string // use []byteint256/uint256 ?? 31 | } 32 | 33 | 34 | // bin(ary) bytes and integer number to (conversion) string helpers 35 | func binToStr( bytes []byte ) string { 36 | return hex.EncodeToString( bytes ) 37 | } 38 | 39 | func intToStr( num int64 ) string { 40 | return strconv.FormatInt( num, 10 ) 41 | } 42 | 43 | 44 | func calcHash( data string ) string { 45 | hashed := sha256.Sum256( []byte(data) ) 46 | return binToStr( hashed[:] ) // note: [:] converts [32]byte to []byte 47 | } 48 | 49 | 50 | func NewBlock(data string, prev string) Block { 51 | t := time.Now().Unix() 52 | hash := calcHash( intToStr(t) + prev + data ) 53 | 54 | return Block { t, data, prev, hash } 55 | } 56 | 57 | 58 | func main() { 59 | b0 := NewBlock( "Hello, Cryptos!", "0000000000000000000000000000000000000000000000000000000000000000" ) 60 | b1 := NewBlock( "Hello, Cryptos! - Hello, Cryptos!", b0.Hash ) 61 | 62 | fmt.Println( b0 ) 63 | // {1522687834 Hello, Cryptos! 64 | // 0000000000000000000000000000000000000000000000000000000000000000 65 | // d85da0f449ff9ddc2c5ba638b23b9524381811227eb463b8c9e0be40dc1b1a8a} 66 | fmt.Println( len( b0.Hash )) 67 | // => 64 68 | fmt.Println( len( b0.Prev )) 69 | // => 64 70 | 71 | fmt.Println( b1 ) 72 | // {1522687834 Hello, Cryptos! - Hello, Cryptos! 73 | // d85da0f449ff9ddc2c5ba638b23b9524381811227eb463b8c9e0be40dc1b1a8a 74 | // e48ba730165d88e15435483fc3a60714be526096a0c9a71ad10623340e33c7e3} 75 | fmt.Println( len( b1.Hash )) 76 | // => 64 77 | fmt.Println( len( b1.Prev )) 78 | // => 64 79 | 80 | blockchain := []Block {b0, b1} 81 | fmt.Println( blockchain ) 82 | // => [{1522687834 Hello, Cryptos! 83 | // 0000000000000000000000000000000000000000000000000000000000000000 84 | // d85da0f449ff9ddc2c5ba638b23b9524381811227eb463b8c9e0be40dc1b1a8a} 85 | // {1522687834 Hello, Cryptos! - Hello, Cryptos! 86 | // d85da0f449ff9ddc2c5ba638b23b9524381811227eb463b8c9e0be40dc1b1a8a 87 | // e48ba730165d88e15435483fc3a60714be526096a0c9a71ad10623340e33c7e3}] 88 | } 89 | -------------------------------------------------------------------------------- /blockchain.rb/blockchain.rb: -------------------------------------------------------------------------------- 1 | ########################### 2 | # build your own blockchain from scratch in 20 lines of ruby! 3 | # 4 | # inspired by 5 | # Let's Build the Tiniest Blockchain In Less Than 50 Lines of Python by Gerald Nash 6 | # see https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b 7 | # 8 | # 9 | # to run use: 10 | # $ ruby ./blockchain.rb 11 | 12 | 13 | require "digest" # for hash checksum digest function SHA256 14 | require "pp" # for pp => pretty printer 15 | 16 | 17 | class Block 18 | 19 | attr_reader :index 20 | attr_reader :timestamp 21 | attr_reader :data 22 | attr_reader :previous_hash 23 | attr_reader :hash 24 | 25 | def initialize(index, data, previous_hash) 26 | @index = index 27 | @timestamp = Time.now 28 | @data = data 29 | @previous_hash = previous_hash 30 | @hash = calc_hash 31 | end 32 | 33 | def calc_hash 34 | sha = Digest::SHA256.new 35 | sha.update( @index.to_s + @timestamp.to_s + @data + @previous_hash ) 36 | sha.hexdigest 37 | end 38 | 39 | 40 | def self.first( data="Genesis" ) # create genesis (big bang! first) block 41 | ## uses index zero (0) and arbitrary previous_hash ("0") 42 | Block.new( 0, data, "0" ) 43 | end 44 | 45 | def self.next( previous, data="Transaction Data..." ) 46 | Block.new( previous.index+1, data, previous.hash ) 47 | end 48 | 49 | end # class Block 50 | 51 | 52 | ##### 53 | ## let's get started 54 | ## build a blockchain a block at a time 55 | 56 | b0 = Block.first( "Genesis" ) 57 | b1 = Block.next( b0, "Transaction Data..." ) 58 | b2 = Block.next( b1, "Transaction Data......" ) 59 | b3 = Block.next( b2, "More Transaction Data..." ) 60 | 61 | blockchain = [b0, b1, b2, b3] 62 | 63 | pp blockchain 64 | 65 | ###### 66 | # will pretty print (pp) something like: 67 | # 68 | # [#, 74 | # #, 80 | # #, 86 | # #] 92 | -------------------------------------------------------------------------------- /blockchain.py/blockchain.py: -------------------------------------------------------------------------------- 1 | ########################### 2 | # build your own blockchain from scratch in python3! 3 | # 4 | # inspired by 5 | # Let's Build the Tiniest Blockchain In Less Than 50 Lines of Python by Gerald Nash 6 | # see https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b 7 | # 8 | # 9 | # to run use: 10 | # $ python ./blockchain.py 11 | 12 | import hashlib as hasher 13 | import datetime as date 14 | import pprint 15 | 16 | 17 | class Block: 18 | def __init__( self, index, data, previous_hash ): 19 | self.index = index 20 | self.timestamp = date.datetime.now() 21 | self.data = data 22 | self.previous_hash = previous_hash 23 | self.hash = self.calc_hash() 24 | 25 | def calc_hash( self ): 26 | sha = hasher.sha256() 27 | sha.update(str(self.index).encode("utf-8") + 28 | str(self.timestamp).encode("utf-8") + 29 | str(self.data).encode("utf-8") + 30 | str(self.previous_hash).encode("utf-8")) 31 | return sha.hexdigest() 32 | 33 | def __repr__( self ): 34 | return "Block<\n index: {},\n timestamp: {},\n data: {},\n previous_hash: {},\n hash: {}>".format( 35 | self.index, self.timestamp, self.data, self.previous_hash, self.hash) 36 | 37 | 38 | @staticmethod 39 | def first( data="Genesis" ): 40 | return Block( 0, data, "0" ) 41 | 42 | @staticmethod 43 | def next( previous, data="Transaction Data..." ): 44 | return Block( previous.index + 1, data, previous.hash ) 45 | 46 | 47 | 48 | ##### 49 | ## let's get started 50 | ## build a blockchain a block at a time 51 | 52 | b0 = Block.first( "Genesis" ) 53 | b1 = Block.next( b0, "Transaction Data..." ) 54 | b2 = Block.next( b1, "Transaction Data......" ) 55 | b3 = Block.next( b2, "More Transaction Data..." ) 56 | 57 | 58 | blockchain = [b0, b1, b2, b3] 59 | 60 | pprint.pprint( blockchain ) 61 | 62 | ###### 63 | # will pretty print something like: 64 | # 65 | # [Block< 66 | # index: 0, 67 | # timestamp: 2017-09-19 19:21:04.015584, 68 | # data: Genesis, 69 | # previous_hash: 0, 70 | # hash: b0cb7953bfad60415ea3b5d3b8015ee22c89d43351ea8f53e5367ee06193b1d3>, 71 | # Block< 72 | # index: 1, 73 | # timestamp: 2017-09-19 19:21:04.015584, 74 | # data: Transaction Data..., 75 | # previous_hash: b0cb7953bfad60415ea3b5d3b8015ee22c89d43351ea8f53e5367ee06193b1d3, 76 | # hash: a87707b2867d28e7367c74e4a2800ec112ea2a8b1517a332ad0b4c49c3b3d60b>, 77 | # Block< 78 | # index: 2, 79 | # timestamp: 2017-09-19 19:21:04.015584, 80 | # data: Transaction Data......, 81 | # previous_hash: a87707b2867d28e7367c74e4a2800ec112ea2a8b1517a332ad0b4c49c3b3d60b, 82 | # hash: 9a8aecdd62da47301502f0079aa1bf24dcf39ad392c723baef6b9bfbc927cf4e>, 83 | # Block< 84 | # index: 3, 85 | # timestamp: 2017-09-19 19:21:04.015584, 86 | # data: More Transaction Data..., 87 | # previous_hash: 9a8aecdd62da47301502f0079aa1bf24dcf39ad392c723baef6b9bfbc927cf4e, 88 | # hash: 5ef442875fb8c3e18d08531f3eba26ea75b608604fa0cc75715d76e15edbb5ea>] 89 | -------------------------------------------------------------------------------- /blockchain.js/blockchain.js: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////// 2 | // build your own blockchain from scratch in 20 lines of javascript! 3 | // 4 | // inspired by 5 | // Let's Build the Tiniest Blockchain In Less Than 50 Lines of Python by Gerald Nash 6 | // see https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b 7 | // 8 | // 9 | // to run use: 10 | // $ npm install -- or npm install -g js-sha256 11 | // $ node ./blockchain.js 12 | 13 | 14 | const SHA256 = require( "js-sha256" ) // for hash checksum digest function SHA256 15 | 16 | 17 | class Block { 18 | 19 | constructor(index, data, previousHash) { 20 | this.index = index 21 | this.timestamp = new Date() 22 | this.data = data 23 | this.previousHash = previousHash 24 | this.hash = this.calcHash() 25 | } 26 | 27 | calcHash() { 28 | var sha = SHA256.create() 29 | sha.update( this.index.toString() + this.timestamp.toString() + this.data + this.previousHash ) 30 | return sha.hex() 31 | } 32 | 33 | static first( data="Genesis" ) { // create genesis (big bang! first) block 34 | // uses index zero (0) and arbitrary previousHash ("0") 35 | return new Block( 0, data, "0" ) 36 | } 37 | 38 | static next( previous, data="Transaction Data..." ) { 39 | return new Block( previous.index+1, data, previous.hash ) 40 | } 41 | } 42 | 43 | 44 | ////// 45 | // let's get started 46 | // build a blockchain a block at a time 47 | 48 | b0 = Block.first( "Genesis" ) 49 | b1 = Block.next( b0, "Transaction Data..." ) 50 | b2 = Block.next( b1, "Transaction Data......" ) 51 | b3 = Block.next( b2, "More Transaction Data..." ) 52 | 53 | 54 | blockchain = [b0, b1, b2, b3] 55 | 56 | console.log( blockchain ) 57 | 58 | ////////////////////////////////// 59 | // will log something like: 60 | // 61 | // [ Block { 62 | // index: 0, 63 | // timestamp: 2017-09-18T08:25:54.162Z, 64 | // data: 'Genesis', 65 | // previousHash: '0', 66 | // hash: 'c396de4c03ddb5275661982adc75ce5fc5905d2a2457d1266c74436c1f3c50f1' }, 67 | // Block { 68 | // index: 1, 69 | // timestamp: 2017-09-18T08:25:54.178Z, 70 | // data: 'Transaction Data...', 71 | // previousHash: 'c396de4c03ddb5275661982adc75ce5fc5905d2a2457d1266c74436c1f3c50f1', 72 | // hash: '493131e09c069645c82795c96e4715cea0f5558be514b5096d853a5b9899154a' }, 73 | // Block { 74 | // index: 2, 75 | // timestamp: 2017-09-18T08:25:54.178Z, 76 | // data: 'Transaction Data......', 77 | // previousHash: '493131e09c069645c82795c96e4715cea0f5558be514b5096d853a5b9899154a', 78 | // hash: '97aa3cb5052615d60ff8e6b41bef606562588c4874f011970ac2f218e2f0f4a8' }, 79 | // Block { 80 | // index: 3, 81 | // timestamp: 2017-09-18T08:25:54.178Z, 82 | // data: 'More Transaction Data...', 83 | // previousHash: '97aa3cb5052615d60ff8e6b41bef606562588c4874f011970ac2f218e2f0f4a8', 84 | // hash: 'e10e020f832e46c2b60e1c3c0412bd370b2fde5f0f782c16eb87d0313ea0d3a3' } ] 85 | -------------------------------------------------------------------------------- /blockchain.kt/blockchain-with-proof-of-work.kts: -------------------------------------------------------------------------------- 1 | import java.security.MessageDigest 2 | import java.time.Instant 3 | 4 | class Block( 5 | val index: Int, 6 | val data: Any, 7 | val previousHash: String, 8 | var difficulty: Int = 2 // This is an example 9 | ) { 10 | val timestamp = Instant.now() 11 | val hash = computeHashWithProofOfWork() 12 | var nonce = 0 13 | 14 | fun next(data: Any) = Block(index + 1, data, hash) 15 | 16 | private fun computeHashWithProofOfWork(): String { 17 | val hashPrefix = "0".repeat(difficulty) 18 | fun hashWithNonce(difficulty: Int) = sha256 19 | .digest("$difficulty$index$timestamp$data$previousHash".toByteArray()) 20 | .joinToString("") { "%02x".format(it) } 21 | 22 | for (nonce in 0..Int.MAX_VALUE) { 23 | val hash = hashWithNonce(nonce) 24 | if (hash.startsWith(hashPrefix)) { 25 | this.nonce = nonce 26 | return hash 27 | } 28 | } 29 | 30 | throw IllegalStateException("Unable to complete work: $this") 31 | } 32 | 33 | override fun toString(): String { 34 | return "Block(data=$data, hash=$hash, index=$index, difficulty=$difficulty, nonce=$nonce, previousHash=$previousHash, timestamp=$timestamp)" 35 | } 36 | 37 | companion object { 38 | private val sha256 = MessageDigest.getInstance("SHA-256") 39 | 40 | fun first(data: Any = "Genesis") = Block(0, data, "0") 41 | } 42 | } 43 | 44 | /** 45 | * Will pretty print (without line wrapping) something like: 46 | * ``` 47 | * [Block(data=Genesis, 48 | * hash=004ba69ea184a25a02a7fbfe5d9c574df925c6a65a14b0e2c14811c5a9e93997, 49 | * index=0, 50 | * difficulty=2, 51 | * nonce=378, 52 | * previousHash=0, 53 | * timestamp=2019-12-29T18:51:48.763407Z), 54 | * Block(data=Transaction Data..., 55 | * hash=00e1bf3a24ae4f9891a78a34ac6b20681605366010cb06f15700efb205e3534e, 56 | * index=1, 57 | * difficulty=2, 58 | * nonce=11, 59 | * previousHash=004ba69ea184a25a02a7fbfe5d9c574df925c6a65a14b0e2c14811c5a9e93997, 60 | * timestamp=2019-12-29T18:51:48.827031Z), 61 | * Block(data=Transaction Data......, 62 | * hash=00d8f64fa17057247524e2d1fb861b11e63df8b20dbd21f63129dcbd00f58809, 63 | * index=2, 64 | * difficulty=2, 65 | * nonce=277, 66 | * previousHash=00e1bf3a24ae4f9891a78a34ac6b20681605366010cb06f15700efb205e3534e, t 67 | * imestamp=2019-12-29T18:51:48.827810Z), 68 | * Block(data=More Transaction Data..., 69 | * hash=00246f05ad6d62cbe9cac9eb09c997e9031268033556cbc75d79f0ae16400821, 70 | * index=3, 71 | * difficulty=2, 72 | * nonce=510, 73 | * previousHash=00d8f64fa17057247524e2d1fb861b11e63df8b20dbd21f63129dcbd00f58809, 74 | * timestamp=2019-12-29T18:51:48.842315Z)] 75 | * ``` 76 | */ 77 | val b0 = Block.first("Genesis") 78 | val b1 = b0.next("Transaction Data...") 79 | val b2 = b1.next("Transaction Data......") 80 | val b3 = b2.next("More Transaction Data...") 81 | 82 | val blockchain = listOf(b0, b1, b2, b3) 83 | 84 | println(blockchain) 85 | -------------------------------------------------------------------------------- /sha256/hashrate.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | "crypto/sha256" 6 | "strings" 7 | "time" 8 | "encoding/hex" 9 | "strconv" 10 | ) 11 | 12 | 13 | 14 | func binToHex( bytes []byte ) string { 15 | return hex.EncodeToString( bytes ) 16 | } 17 | 18 | func int64ToStr( num int64 ) string { 19 | return strconv.FormatInt( num, 10 ) 20 | } 21 | 22 | 23 | 24 | func calcHash( data string ) string { 25 | hashed := sha256.Sum256( []byte(data) ) 26 | return binToHex( hashed[:] ) // note: use [:] to convert [32]byte to slice ([]byte) 27 | } 28 | 29 | func computeHashWithProofOfWork( data string, difficulty string ) (int64,string) { 30 | nonce := int64( 0 ) 31 | for { 32 | hash := calcHash( int64ToStr(nonce) + data ) 33 | 34 | if strings.HasPrefix( hash, difficulty ) { 35 | return nonce,hash // bingo! proof of work if hash starts with leading zeros (00) 36 | } else { 37 | nonce += 1 // keep trying (and trying and trying) 38 | } 39 | } 40 | } 41 | 42 | 43 | 44 | func main() { 45 | 46 | factors := []int{1,2,3,4,5,6} // add 7 (~10 mins) 47 | 48 | for _, factor := range factors { 49 | difficulty := strings.Repeat( "0", factor ) 50 | fmt.Printf( "Difficulty: %s (%d bits)\n", difficulty, len(difficulty)*4 ) 51 | } 52 | 53 | 54 | for _, factor := range factors { 55 | difficulty := strings.Repeat( "0", factor ) 56 | fmt.Printf( "\nDifficulty: %s (%d bits)\n", difficulty, len(difficulty)*4 ) 57 | 58 | fmt.Println( "Starting search..." ) 59 | t1 := time.Now() 60 | nonce, _ := computeHashWithProofOfWork( "Hello, Cryptos!", difficulty ) 61 | t2 := time.Now() 62 | 63 | delta := t2.Sub( t1 ) 64 | fmt.Printf( "Elapsed Time: %s, Hashes Calculated: %d\n", delta, nonce ) 65 | 66 | if delta.Seconds() > 0.001 { 67 | hashrate := float64(nonce)/delta.Seconds() 68 | fmt.Printf( "Hash Rate: %d hashes per second\n", int64(hashrate)) 69 | } 70 | } 71 | } 72 | 73 | 74 | // Difficulty: 0 (4 bits) 75 | // Difficulty: 00 (8 bits) 76 | // Difficulty: 000 (12 bits) 77 | // Difficulty: 0000 (16 bits) 78 | // Difficulty: 00000 (20 bits) 79 | // Difficulty: 000000 (24 bits) 80 | // 81 | // Difficulty: 0 (4 bits) 82 | // Starting search... 83 | // Elapsed Time: 0s, Hashes Calculated: 56 84 | // 85 | // Difficulty: 00 (8 bits) 86 | // Starting search... 87 | // Elapsed Time: 1.0001ms, Hashes Calculated: 143 88 | // Hash Rate: 142985 hashes per second 89 | // 90 | // Difficulty: 000 (12 bits) 91 | // Starting search... 92 | // Elapsed Time: 5.0002ms, Hashes Calculated: 3834 93 | // Hash Rate: 766769 hashes per second 94 | // 95 | // Difficulty: 0000 (16 bits) 96 | // Starting search... 97 | // Elapsed Time: 33.0019ms, Hashes Calculated: 26762 98 | // Hash Rate: 810923 hashes per second 99 | // 100 | // Difficulty: 00000 (20 bits) 101 | // Starting search... 102 | // Elapsed Time: 137.0078ms, Hashes Calculated: 118592 103 | // Hash Rate: 865585 hashes per second 104 | // 105 | // Difficulty: 000000 (24 bits) 106 | // Starting search... 107 | // Elapsed Time: 26.5378148s, Hashes Calculated: 21554046 108 | // Hash Rate: 812201 hashes per second 109 | -------------------------------------------------------------------------------- /blockchain.js/blockchain_with_proof_of_work.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // to run use: 3 | // $ npm install -- or npm install -g js-sha256 4 | // $ node ./blockchain_with_proof_of_work.js 5 | 6 | 7 | const SHA256 = require( "js-sha256" ) // for hash checksum digest function SHA256 8 | 9 | 10 | class Block { 11 | 12 | constructor(index, data, previousHash) { 13 | this.index = index 14 | this.timestamp = new Date() 15 | this.data = data 16 | this.previousHash = previousHash 17 | this.nonce, this.hash = this.computeHashWithProofOfWork() 18 | } 19 | 20 | computeHashWithProofOfWork( difficulty="00" ) { 21 | var nonce = 0 22 | while( true ) { 23 | var hash = this.calcHashWithNonce( nonce ) 24 | if( hash.startsWith( difficulty )) 25 | return nonce, hash // bingo! proof of work if hash starts with leading zeros (00) 26 | else 27 | nonce += 1 // keep trying (and trying and trying) 28 | } 29 | } 30 | 31 | calcHashWithNonce( nonce=0 ) { 32 | var sha = SHA256.create() 33 | sha.update( nonce.toString() + this.index.toString() + this.timestamp.toString() + this.data + this.previousHash ) 34 | return sha.hex() 35 | } 36 | 37 | 38 | static first( data="Genesis" ) { // create genesis (big bang! first) block 39 | // uses index zero (0) and arbitrary previousHash ("0") 40 | return new Block( 0, data, "0" ) 41 | } 42 | 43 | static next( previous, data="Transaction Data..." ) { 44 | return new Block( previous.index+1, data, previous.hash ) 45 | } 46 | } 47 | 48 | 49 | ////// 50 | // let's get started 51 | // build a blockchain a block at a time 52 | 53 | b0 = Block.first( "Genesis" ) 54 | b1 = Block.next( b0, "Transaction Data..." ) 55 | b2 = Block.next( b1, "Transaction Data......" ) 56 | b3 = Block.next( b2, "More Transaction Data..." ) 57 | 58 | 59 | blockchain = [b0, b1, b2, b3] 60 | 61 | console.log( blockchain ) 62 | 63 | 64 | 65 | ////////////////////////////////// 66 | // will log something like: 67 | // 68 | // [ Block { 69 | // index: 0, 70 | // timestamp: 2017-09-22T18:08:36.587Z, 71 | // data: 'Genesis', 72 | // previousHash: '0', 73 | // hash: '003dabacd06e208f5c5625777a49778e279516e0b43f6126a478a68791bd9789' }, 74 | // Block { 75 | // index: 1, 76 | // timestamp: 2017-09-22T18:08:36.603Z, 77 | // data: 'Transaction Data...', 78 | // previousHash: '003dabacd06e208f5c5625777a49778e279516e0b43f6126a478a68791bd9789', 79 | // hash: '006760687f42f82d4ba93b7b6c8459184b8e871608ffc230f2bbe6af6c5bd260' }, 80 | // Block { 81 | // index: 2, 82 | // timestamp: 2017-09-22T18:08:36.603Z, 83 | // data: 'Transaction Data......', 84 | // previousHash: '006760687f42f82d4ba93b7b6c8459184b8e871608ffc230f2bbe6af6c5bd260', 85 | // hash: '00a7f2a8d3b718b48ddbbb41cab158e160540625568255e0cbca33c83437f0f7' }, 86 | // Block { 87 | // index: 3, 88 | // timestamp: 2017-09-22T18:08:36.603Z, 89 | // data: 'More Transaction Data...', 90 | // previousHash: '00a7f2a8d3b718b48ddbbb41cab158e160540625568255e0cbca33c83437f0f7', 91 | // hash: '00e9fd5ffbce8c2bc95243c781506b366985ba726a15e02597e42f8598498800' } ] 92 | -------------------------------------------------------------------------------- /blockchain.rs/src/main.rs: -------------------------------------------------------------------------------- 1 | use blockchainlib::*; 2 | 3 | fn main() { 4 | let mut blockchain = Blockchain::new(); 5 | let difficulty = 0x000fffffffffffffffffffffffffffff; 6 | 7 | let mut genesis_block = Block::new(0, now(), vec![0; 32], vec![ 8 | Transaction { 9 | inputs: vec![], 10 | outputs: vec![ 11 | transaction::Output { 12 | to_addr: "Alice".to_owned(), 13 | value: 50, 14 | }, 15 | transaction::Output { 16 | to_addr: "Bob".to_owned(), 17 | value: 7, 18 | } 19 | ] 20 | } 21 | ], difficulty); 22 | genesis_block.mine(); 23 | println!("Mined gen block {:?}", &genesis_block); 24 | 25 | let mut last_hash = genesis_block.hash.clone(); 26 | 27 | blockchain.update_with_block(genesis_block).expect("Failed to add Genesis Block"); 28 | 29 | let mut block = Block::new(1, now(), last_hash, vec![ 30 | Transaction { 31 | inputs: vec![], 32 | outputs: vec![ 33 | transaction::Output { 34 | to_addr: "Chris".to_owned(), 35 | value: 536, 36 | } 37 | ] 38 | }, 39 | Transaction { 40 | inputs: vec![ 41 | transaction::Output { 42 | to_addr: "Alice".to_owned(), 43 | value: 50, 44 | }, 45 | ], 46 | outputs: vec![ 47 | transaction::Output { 48 | to_addr: "Alice".to_owned(), 49 | value: 36, 50 | }, 51 | transaction::Output { 52 | to_addr: "Bob".to_owned(), 53 | value: 12, 54 | } 55 | ] 56 | } 57 | ], difficulty); 58 | block.mine(); 59 | println!("Mined block {:?}", &block); 60 | 61 | last_hash = block.hash.clone(); 62 | 63 | blockchain.update_with_block(block).expect("Failed to add Block"); 64 | 65 | block = Block::new(2, now(), last_hash, vec![ 66 | Transaction { 67 | inputs: vec![], 68 | outputs: vec![ 69 | transaction::Output { 70 | to_addr: "David".to_owned(), 71 | value: 100, 72 | }, 73 | ] 74 | }, 75 | Transaction { 76 | inputs: vec![ 77 | transaction::Output { 78 | to_addr: "Chris".to_owned(), 79 | value: 536, 80 | } 81 | ], 82 | outputs: vec![ 83 | transaction::Output { 84 | to_addr: "David".to_owned(), 85 | value: 30, 86 | }, 87 | transaction::Output { 88 | to_addr: "Chris".to_owned(), 89 | value: 500, 90 | } 91 | ] 92 | } 93 | ], difficulty); 94 | block.mine(); 95 | 96 | println!("Mined block {:?}", &block); 97 | 98 | blockchain.update_with_block(block).expect("Failed to add Block"); 99 | 100 | for i in blockchain.iter() { 101 | println!("{:?}", i); 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /blockchain.rb/blockchain_with_proof_of_work.rb: -------------------------------------------------------------------------------- 1 | ########################### 2 | # build your own blockchain from scratch in ruby! 3 | # 4 | # to run use: 5 | # $ ruby ./blockchain_with_proof_of_work.rb 6 | 7 | 8 | require "digest" # for hash checksum digest function SHA256 9 | require "pp" # for pp => pretty printer 10 | 11 | 12 | class Block 13 | 14 | attr_reader :index 15 | attr_reader :timestamp 16 | attr_reader :data 17 | attr_reader :previous_hash 18 | attr_reader :nonce ## proof of work if hash starts with leading zeros (00) 19 | attr_reader :hash 20 | 21 | def initialize(index, data, previous_hash) 22 | @index = index 23 | @timestamp = Time.now 24 | @data = data 25 | @previous_hash = previous_hash 26 | @nonce, @hash = compute_hash_with_proof_of_work 27 | end 28 | 29 | def compute_hash_with_proof_of_work( difficulty="00" ) 30 | nonce = 0 31 | loop do 32 | hash = calc_hash_with_nonce( nonce ) 33 | if hash.start_with?( difficulty ) 34 | return [nonce,hash] ## bingo! proof of work if hash starts with leading zeros (00) 35 | else 36 | nonce += 1 ## keep trying (and trying and trying) 37 | end 38 | end 39 | end 40 | 41 | def calc_hash_with_nonce( nonce=0 ) 42 | sha = Digest::SHA256.new 43 | sha.update( nonce.to_s + @index.to_s + @timestamp.to_s + @data + @previous_hash ) 44 | sha.hexdigest 45 | end 46 | 47 | 48 | def self.first( data="Genesis" ) # create genesis (big bang! first) block 49 | ## uses index zero (0) and arbitrary previous_hash ("0") 50 | Block.new( 0, data, "0" ) 51 | end 52 | 53 | def self.next( previous, data="Transaction Data..." ) 54 | Block.new( previous.index+1, data, previous.hash ) 55 | end 56 | 57 | end # class Block 58 | 59 | 60 | ##### 61 | ## let's get started 62 | ## build a blockchain a block at a time 63 | 64 | b0 = Block.first( "Genesis" ) 65 | b1 = Block.next( b0, "Transaction Data..." ) 66 | b2 = Block.next( b1, "Transaction Data......" ) 67 | b3 = Block.next( b2, "More Transaction Data..." ) 68 | 69 | blockchain = [b0, b1, b2, b3] 70 | 71 | pp blockchain 72 | 73 | ###### 74 | # will pretty print (pp) something like: 75 | # 76 | # [#, 83 | # #, 91 | # #, 99 | # #] 107 | -------------------------------------------------------------------------------- /blockchain.cpp/blockchain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | string calc_sha256(const string str) { 11 | unsigned char hash[SHA256_DIGEST_LENGTH]; 12 | SHA256_CTX sha256; 13 | SHA256_Init(&sha256); 14 | SHA256_Update(&sha256, str.c_str(), str.size()); 15 | SHA256_Final(hash, &sha256); 16 | stringstream ss; 17 | for(int i = 0; i < SHA256_DIGEST_LENGTH; i++) { 18 | ss << hex << setw(2) << setfill('0') << (int)hash[i]; 19 | } 20 | return ss.str(); 21 | } 22 | 23 | class Block { 24 | private: 25 | string data; 26 | string previous_hash; 27 | string timestamp; 28 | 29 | 30 | public: 31 | int index; 32 | string hash; 33 | 34 | Block(int index, string data, string previous_hash) { 35 | this->index = index; 36 | 37 | std::time_t result = std::time(nullptr); 38 | this->timestamp = asctime(std::localtime(&result)); 39 | this->timestamp.pop_back(); 40 | 41 | this->data = data; 42 | this->previous_hash = previous_hash; 43 | this->hash = calc_hash(); 44 | } 45 | 46 | string calc_hash() { 47 | string sha= to_string(this->index) + 48 | this->timestamp + 49 | this->data + 50 | this->previous_hash; 51 | sha = calc_sha256(sha); 52 | return sha; 53 | } 54 | 55 | string sstr() { 56 | stringstream ss; 57 | ss<< "Block<\n index: "<< this->index<<",\n timestamp: "<< 58 | this->timestamp<<",\n data: "<data<<",\n previous_hash: "<< 59 | this->previous_hash<<",\n hash: "<hash< blockchain{b0, b1, b2, b3}; 78 | for(Block v: blockchain) { 79 | cout<".format( 42 | self.index, self.timestamp, self.data, self.previous_hash, self.nonce, self.hash) 43 | 44 | 45 | @staticmethod 46 | def first( data="Genesis" ): 47 | return Block( 0, data, "0" ) 48 | 49 | @staticmethod 50 | def next( previous, data="Transaction Data..." ): 51 | return Block( previous.index+1, data, previous.hash ) 52 | 53 | 54 | 55 | ##### 56 | ## let's get started 57 | ## build a blockchain a block at a time 58 | 59 | b0 = Block.first( "Genesis" ) 60 | b1 = Block.next( b0, "Transaction Data..." ) 61 | b2 = Block.next( b1, "Transaction Data......" ) 62 | b3 = Block.next( b2, "More Transaction Data..." ) 63 | 64 | 65 | blockchain = [b0, b1, b2, b3] 66 | 67 | pprint.pprint( blockchain ) 68 | 69 | ###### 70 | # will pretty print something like: 71 | # 72 | # [Block< 73 | # index: 0, 74 | # timestamp: 2017-09-21 08:20:55.369288, 75 | # data: Genesis, 76 | # previous_hash: 0, 77 | # nonce: 522, 78 | # hash: 00f8d728c43331952794b6a9684a5c9838cdf9dc5664f218c8b84722d3ee9eae>, 79 | # Block< 80 | # index: 1, 81 | # timestamp: 2017-09-21 08:20:55.374494, 82 | # data: Transaction Data..., 83 | # previous_hash: 00f8d728c43331952794b6a9684a5c9838cdf9dc5664f218c8b84722d3ee9eae, 84 | # nonce: 80, 85 | # hash: 00f2ef4939c5ff5572f38b82907594a02cfcad01c815e8370dd10b3b912120a0>, 86 | # Block< 87 | # index: 2, 88 | # timestamp: 2017-09-21 08:20:55.374494, 89 | # data: Transaction Data......, 90 | # previous_hash: 00f2ef4939c5ff5572f38b82907594a02cfcad01c815e8370dd10b3b912120a0, 91 | # nonce: 19, 92 | # hash: 0004d93f5759596f423c9d91c8cb75b7cb38952b05da7842226c5bf93ce43902>, 93 | # Block< 94 | # index: 3, 95 | # timestamp: 2017-09-21 08:20:55.390116, 96 | # data: More Transaction Data..., 97 | # previous_hash: 0004d93f5759596f423c9d91c8cb75b7cb38952b05da7842226c5bf93ce43902, 98 | # nonce: 325, 99 | # hash: 001b8d1567dacf94ac036644a290212697a2ece6757951018beecd6cf3c076b2>] 100 | -------------------------------------------------------------------------------- /blockchain.go/blockchain_with_proof_of_work.go: -------------------------------------------------------------------------------- 1 | ///// 2 | // build your own blockchain from scratch in go(lang) 3 | // 4 | // references: 5 | // - https://jeiwan.cc/posts/building-blockchain-in-go-part-1/ 6 | // - https://jeiwan.cc/posts/building-blockchain-in-go-part-2/ 7 | // - https://medium.com/@mycoralhealth/code-your-own-blockchain-in-less-than-200-lines-of-go-e296282bcffc 8 | // - https://medium.com/@mycoralhealth/code-your-own-blockchain-mining-algorithm-in-go-82c6a71aba1f 9 | // - and (many) others 10 | // 11 | // to run use: 12 | // $ go run blockchain_with_proof_of_work.go 13 | 14 | 15 | 16 | package main 17 | 18 | import ( 19 | "fmt" 20 | "crypto/sha256" 21 | "encoding/hex" 22 | "time" 23 | "strconv" 24 | "strings" 25 | ) 26 | 27 | type Block struct { 28 | Time int64 // seconds since (unix) epoch (1970-01-01) 29 | Data string 30 | Prev string // use []byte/int256/uint256 ?? 31 | Hash string // use []byteint256/uint256 ?? 32 | Nonce int64 // number used once - lucky (mining) lottery number 33 | } 34 | 35 | 36 | // bin(ary) bytes and integer number to (conversion) string helpers 37 | func binToStr( bytes []byte ) string { 38 | return hex.EncodeToString( bytes ) 39 | } 40 | 41 | func intToStr( num int64 ) string { 42 | return strconv.FormatInt( num, 10 ) 43 | } 44 | 45 | 46 | 47 | func calcHash( data string ) string { 48 | hashed := sha256.Sum256( []byte(data) ) 49 | return binToStr( hashed[:] ) // note: [:] converts [32]byte to []byte 50 | } 51 | 52 | func computeHashWithProofOfWork( data string, difficulty string ) (int64,string) { 53 | nonce := int64( 0 ) 54 | for { 55 | hash := calcHash( intToStr(nonce) + data ) 56 | if strings.HasPrefix( hash, difficulty ) { 57 | return nonce,hash // bingo! proof of work if hash starts with leading zeros (00) 58 | } else { 59 | nonce += 1 // keep trying (and trying and trying) 60 | } 61 | } 62 | } 63 | 64 | 65 | func NewBlock( data string, prev string ) Block { 66 | t := time.Now().Unix() 67 | difficulty := "0000" 68 | nonce, hash := computeHashWithProofOfWork( intToStr(t) + prev + data, difficulty ) 69 | 70 | return Block { t, data, prev, hash, nonce } 71 | } 72 | 73 | 74 | func main() { 75 | b0 := NewBlock( "Hello, Cryptos!", "0000000000000000000000000000000000000000000000000000000000000000" ) 76 | b1 := NewBlock( "Hello, Cryptos! - Hello, Cryptos!", b0.Hash ) 77 | 78 | fmt.Println( b0 ) 79 | // {1522691756 Hello, Cryptos! 80 | // 0000000000000000000000000000000000000000000000000000000000000000 81 | // 00009f597a8e28fc42a450c0ed2eff1b6507f76f6a7d1e112686700ce37e3676 82 | // 42278} 83 | fmt.Println( len( b0.Hash )) 84 | // => 64 85 | fmt.Println( len( b0.Prev )) 86 | // => 64 87 | 88 | fmt.Println( b1 ) 89 | // {1522691756 Hello, Cryptos! - Hello, Cryptos! 90 | // 00009f597a8e28fc42a450c0ed2eff1b6507f76f6a7d1e112686700ce37e3676 91 | // 00009ef5ea432f840c3fb23dbedb5cce4c72e2951a140c1289dda1fedbcd6e99 92 | // 105106} 93 | 94 | fmt.Println( len( b1.Hash )) 95 | // => 64 96 | fmt.Println( len( b1.Prev )) 97 | // => 64 98 | 99 | blockchain := []Block {b0, b1} 100 | fmt.Println( blockchain ) 101 | // => [{1522691756 Hello, Cryptos! 102 | // 0000000000000000000000000000000000000000000000000000000000000000 103 | // 00009f597a8e28fc42a450c0ed2eff1b6507f76f6a7d1e112686700ce37e3676 104 | // 42278} 105 | // {1522691756 Hello, Cryptos! - Hello, Cryptos! 106 | // 00009f597a8e28fc42a450c0ed2eff1b6507f76f6a7d1e112686700ce37e3676 107 | // 00009ef5ea432f840c3fb23dbedb5cce4c72e2951a140c1289dda1fedbcd6e99 108 | // 105106}] 109 | } 110 | -------------------------------------------------------------------------------- /blockchain.cpp/blockchain_with_proof_of_work.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | string calc_sha256(const string str) { 11 | unsigned char hash[SHA256_DIGEST_LENGTH]; 12 | SHA256_CTX sha256; 13 | SHA256_Init(&sha256); 14 | SHA256_Update(&sha256, str.c_str(), str.size()); 15 | SHA256_Final(hash, &sha256); 16 | stringstream ss; 17 | for(int i = 0; i < SHA256_DIGEST_LENGTH; i++) { 18 | ss << hex << setw(2) << setfill('0') << (int)hash[i]; 19 | } 20 | return ss.str(); 21 | } 22 | 23 | class Block { 24 | private: 25 | string data; 26 | string previous_hash; 27 | string timestamp; 28 | int nounce; 29 | 30 | public: 31 | int index; 32 | string hash; 33 | 34 | Block(int index, string data, string previous_hash) { 35 | this->index = index; 36 | 37 | std::time_t result = std::time(nullptr); 38 | this->timestamp = asctime(std::localtime(&result)); 39 | this->timestamp.pop_back(); 40 | 41 | this->data = data; 42 | this->previous_hash = previous_hash; 43 | tie(this->nounce, this->hash) = compute_hash_with_proof_of_work(); 44 | } 45 | 46 | pair compute_hash_with_proof_of_work(string difficulty="00") { 47 | int nounce = 0; 48 | while(true) { 49 | string hash_nounce = calc_hash_with_nounce(nounce); 50 | if(hash_nounce.find(difficulty) == 0) { 51 | return make_pair(nounce, hash_nounce); 52 | } 53 | else { 54 | ++nounce; 55 | } 56 | } 57 | } 58 | 59 | string calc_hash_with_nounce(int nounce) { 60 | string sha = to_string(nounce) + 61 | to_string(this->index) + 62 | this->timestamp + 63 | this->data + 64 | this->previous_hash; 65 | return calc_sha256(sha); 66 | } 67 | 68 | string sstr() { 69 | stringstream ss; 70 | ss<< "Block<\n index: "<< this->index<<",\n timestamp: "<< 71 | this->timestamp<<",\n data: "<data<<",\n previous_hash: "<< 72 | this->previous_hash<<",\n nounce: "<nounce<<",\n hash: "<< 73 | this->hash< blockchain{b0, b1, b2, b3}; 95 | for(Block v: blockchain) { 96 | cout< cannot use hashed (type [32]byte) as type []byte in argument to hex.EncodeToString 30 | // return hex.EncodeToString( hashed ) 31 | 32 | // or single line => return hex.EncodeToString( sha256.Sum256( bytes ) )) 33 | } 34 | 35 | 36 | func calcHashFromString( str string ) string { 37 | h := sha256.New() 38 | h.Write( []byte(str) ) 39 | hashed := h.Sum( nil ) // check why nil para? 40 | return hex.EncodeToString(hashed) 41 | } 42 | 43 | func calcHash( data interface{} ) string { 44 | 45 | h := sha256.New() 46 | 47 | switch v := data.(type) { 48 | default: 49 | fmt.Printf( "calcHash - unexpected type %T", v ) // panic!! why? why not? 50 | case []byte: 51 | h.Write( v ) 52 | case string: 53 | h.Write( []byte(v) ) 54 | } 55 | 56 | hashed := h.Sum( nil ) // check why nil para? 57 | return hex.EncodeToString(hashed) 58 | } 59 | 60 | 61 | func main() { 62 | 63 | fmt.Printf( "%x\n", sha256.Sum256( []byte("Hello, Cryptos!") )) 64 | 65 | 66 | fmt.Println( calcHashFromBytesV1( []byte("Hello, Cryptos!") )) 67 | fmt.Println( calcHashFromBytesV2( []byte("Hello, Cryptos!") )) 68 | fmt.Println( calcHashFromString( "Hello, Cryptos!" )) 69 | 70 | fmt.Println( calcHash( "Hello, Cryptos!" )) 71 | fmt.Println( calcHash( []byte("Hello, Cryptos!") )) 72 | 73 | 74 | fmt.Println( calcHash( "Hello, Cryptos! - Hello, Cryptos! - Hello, Cryptos!" )) 75 | 76 | fmt.Println( calcHash( "Your Name Here" )) 77 | fmt.Println( calcHash( "Data Data Data Data" )) 78 | 79 | fmt.Println( calcHash( `Data Data Data Data Data Data 80 | Data Data Data Data Data Data 81 | Data Data Data Data Data Data 82 | Data Data Data Data Data Data 83 | Data Data Data Data Data Data` )) 84 | 85 | 86 | // from a file 87 | // -- alternative - use f=os.Open(".txt") and io.Copy( h, f ) 88 | // 89 | txt, err := ioutil.ReadFile( "./transactions.txt" ) 90 | if err != nil { 91 | fmt.Printf( "Error in reading file: %s\n", err ) 92 | // use log.Fatal(err) -- why? why not?? 93 | } else { 94 | fmt.Println( calcHash( txt ) ) 95 | } 96 | 97 | 98 | fmt.Println( len(calcHash( "Hello, Cryptos!" ))) 99 | // => 64 100 | fmt.Println( len(calcHash( "Hello, Cryptos! - Hello, Cryptos! - Hello, Cryptos!" ))) 101 | // => 64 102 | 103 | hex := calcHash( "Hello, Cryptos!" ) 104 | fmt.Println( hex ) 105 | 106 | 107 | 108 | n, err := strconv.ParseInt( hex, 16, 64 ) 109 | if err != nil { 110 | fmt.Printf( "Error in conversion: %s\n", err ) 111 | } else { 112 | fmt.Println( n ) 113 | } 114 | 115 | // Error in conversion: strconv.ParseInt: 116 | // parsing "33eedea60b0662c66c289ceba71863a864cf84b00e10002ca1069bf58f9362d5": 117 | // value out of range !!!! 118 | // 119 | // 120 | // todo: print - biggest largest possible uint64 number 121 | 122 | // 123 | // how to deal with uint256 124 | // see https://ethereum.stackexchange.com/questions/20859/how-generate-number-type-uint256-in-go 125 | 126 | 127 | big := new(big.Int) 128 | big, ok := big.SetString( hex, 16 ) 129 | if !ok { 130 | fmt.Println( "SetString: error" ) 131 | } else { 132 | fmt.Println( big ) 133 | // => 23490001543365037720284007500157053051505610714786813679598750288695740555989 134 | fmt.Println( big.Text( 2 )) 135 | // => 11001111101110110111101010011000001011000001100110001011000... 136 | } 137 | 138 | 139 | 140 | 141 | 142 | n, _ = strconv.ParseInt( "33ee", 16, 64 ) 143 | fmt.Println( n ) 144 | // => 13294 145 | 146 | 147 | 148 | n, _ = strconv.ParseInt( "33ee", 16, 64 ) 149 | b := strconv.FormatInt( n, 2 ) 150 | fmt.Println( b ) 151 | // => 11001111101110 152 | 153 | } 154 | 155 | /* 156 | 33eedea60b0662c66c289ceba71863a864cf84b00e10002ca1069bf58f9362d5 157 | c4b5e2b9685062ecca5d0f6f6ba605b3f99eafed3a3729d2ae1ccaa2b440b1cc 158 | 39459289c09c33a7b516bef926c1873c6ecd2e6db09218b065d7465b6736f801 159 | a7bbfc531b2ecf641b9abcd7ad8e50267e1c873e5a396d1919f504973090565a 160 | */ 161 | -------------------------------------------------------------------------------- /blockchain.rs/src/blockchain.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use std::collections::HashSet; 3 | 4 | pub struct Blockchain { 5 | pub head: Link, 6 | pub no_of_blocks: i32, 7 | unspent_outputs: HashSet, 8 | } 9 | 10 | type Link = Option>>; 11 | 12 | pub struct Node { 13 | elem: Block, 14 | next: Link, 15 | } 16 | 17 | pub struct Iter<'a, Block> { 18 | next: Option<&'a Node>, 19 | } 20 | 21 | 22 | #[derive(Debug)] 23 | pub enum BlockChainValidationErr { 24 | MismatchIndex, 25 | InvalidHash, 26 | AchronologicalTimestamp, 27 | InvalidPrevBlock, 28 | MismatchPreviousHash, 29 | InvalidGenisisBlockFormat, 30 | InvalidInput, 31 | InsufficientInputValue, 32 | InvalidCoinbaseTransaction, 33 | } 34 | 35 | impl Blockchain { 36 | pub fn new() -> Self { 37 | Blockchain { 38 | head: None, 39 | no_of_blocks: 0, 40 | unspent_outputs: HashSet::new(), 41 | } 42 | } 43 | 44 | pub fn push(&mut self, block: Block) { 45 | let new_node = Box::new(Node { 46 | elem: block, 47 | next: self.head.take(), 48 | }); 49 | 50 | self.head = Some(new_node); 51 | } 52 | 53 | pub fn peek(&self) -> Option<&Block> { 54 | self.head.as_ref().map(|node| { 55 | &node.elem 56 | }) 57 | } 58 | 59 | pub fn iter(&self) -> Iter { 60 | Iter { next: self.head.as_ref().map(|node| &**node) } 61 | } 62 | 63 | pub fn update_with_block (&mut self, block: Block) -> Result<(), BlockChainValidationErr> { 64 | let i = self.no_of_blocks; 65 | 66 | if block.index != i as u32 { 67 | return Err(BlockChainValidationErr::MismatchIndex); 68 | } else if !block::check_difficulty(&block.hash(), block.difficulty) { 69 | return Err(BlockChainValidationErr::InvalidHash); 70 | } else if i != 0 { 71 | //Another block 72 | let prev_block = self.peek(); 73 | match prev_block { 74 | None => return Err(BlockChainValidationErr::InvalidPrevBlock), 75 | Some(prev_block) => { 76 | if block.timestamp <= prev_block.timestamp { 77 | return Err(BlockChainValidationErr::AchronologicalTimestamp); 78 | } else if block.prev_block_hash != prev_block.hash() { 79 | return Err(BlockChainValidationErr::MismatchPreviousHash); 80 | } 81 | } 82 | } 83 | } else { 84 | //Genesis block 85 | if block.prev_block_hash != vec![0; 32] { 86 | return Err(BlockChainValidationErr::InvalidGenisisBlockFormat); 87 | } 88 | } 89 | 90 | if let Some((coinbase, transactions)) = block.transactions.split_first(){ 91 | if !coinbase.is_coinbase() { 92 | return Err(BlockChainValidationErr::InvalidCoinbaseTransaction); 93 | } 94 | 95 | let mut block_spent: HashSet = HashSet::new(); 96 | let mut block_created: HashSet = HashSet::new(); 97 | let mut total_fee = 0; 98 | 99 | for transaction in transactions { 100 | let input_hashes = transaction.input_hashes(); 101 | 102 | if !(&input_hashes - &self.unspent_outputs).is_empty() || 103 | !(&input_hashes & &block_spent).is_empty() 104 | { 105 | return Err(BlockChainValidationErr::InvalidInput); 106 | } 107 | 108 | let input_value = transaction.input_value(); 109 | let output_value = transaction.output_value(); 110 | 111 | if output_value > input_value { 112 | return Err(BlockChainValidationErr::InsufficientInputValue) 113 | } 114 | 115 | let fee = input_value - output_value; 116 | total_fee += fee; 117 | 118 | block_spent.extend(input_hashes); 119 | block_created.extend(transaction.output_hashes()) 120 | } 121 | 122 | if coinbase.output_value() < total_fee { 123 | return Err(BlockChainValidationErr::InvalidCoinbaseTransaction); 124 | } else { 125 | block_created.extend(coinbase.output_hashes()) 126 | } 127 | 128 | self.unspent_outputs.retain(|output| block_spent.contains(output)); 129 | self.unspent_outputs.extend(block_created); 130 | } 131 | 132 | self.push(block); 133 | 134 | self.no_of_blocks += 1; 135 | 136 | Ok(()) 137 | } 138 | } 139 | 140 | impl<'a, Block> Iterator for Iter<'a, Block> { 141 | type Item = &'a Block; 142 | fn next(&mut self) -> Option { 143 | self.next.map(|node| { 144 | self.next = node.next.as_ref().map(|node| &**node); 145 | &node.elem 146 | }) 147 | } 148 | } 149 | 150 | -------------------------------------------------------------------------------- /TULIPS.md: -------------------------------------------------------------------------------- 1 | # Tulips :tulip::tulip::tulip: on the Blockchain! - Public Distributed (Hyper) Ledger Book 2 | 3 | > Tulips were introduced into the Netherlands in the 16th century. 4 | > These exotic flowers were greatly admired and numerous species were meticulously recorded, 5 | > along with their Latin names, in tulip albums. 6 | > 7 | > -- Rijksmuseum, Amsterdam 8 | 9 | 10 | Learn by Example from the Real World (Anno 1637) - Buy! Sell! Hold! Enjoy the Beauty of Admiral of Admirals, Semper Augustus and More. 11 | 12 | 13 | ## Transactions (Hyper) Ledger Book 14 | 15 | | From | To | What | Qty | 16 | |---------------------|--------------|---------------------------|----:| 17 | | Dutchgrown (†) | Vincent | Tulip Bloemendaal Sunset | 10 | 18 | | Keukenhof (†) | Anne | Tulip Semper Augustus | 7 | 19 | | | | | | 20 | | Flowers (†) | Ruben | Tulip Admiral van Eijck | 5 | 21 | | Vicent | Anne | Tulip Bloemendaal Sunset | 3 | 22 | | Anne | Julia | Tulip Semper Augustus | 1 | 23 | | Julia | Luuk | Tulip Semper Augustus | 1 | 24 | | | | | | 25 | | Bloom & Blossom (†) | Daisy | Tulip Admiral of Admirals | 8 | 26 | | Vincent | Max | Tulip Bloemendaal Sunset | 2 | 27 | | Anne | Martijn | Tulip Semper Augustus | 2 | 28 | | Ruben | Julia | Tulip Admiral van Eijck | 2 | 29 | | | | | | 30 | | Teleflora (†) | Max | Tulip Red Impression | 11 | 31 | | Anne | Naomi | Tulip Bloemendaal Sunset | 1 | 32 | | Daisy | Vincent | Tulip Admiral of Admirals | 3 | 33 | | Julia | Mina | Tulip Admiral van Eijck | 1 | 34 | | | | | | 35 | | Max | Isabel | Tulip Red Impression | 2 | 36 | 37 | (†): Grower Transaction - New Tulips on the Market! 38 | 39 | 40 | 41 | ## Blockchain! Blockchain! Blockchain! 42 | 43 | Let's put the tulips on the blockchain! Example [`awesome-blockchains/blockchain_with_transactions.rb`](https://github.com/openblockchains/awesome-blockchains/blob/master/blockchain.rb/blockchain_with_transactions.rb): 44 | 45 | 46 | ```ruby 47 | b0 = Block.first( 48 | { from: "Dutchgrown", to: "Vincent", what: "Tulip Bloemendaal Sunset", qty: 10 }, 49 | { from: "Keukenhof", to: "Anne", what: "Tulip Semper Augustus", qty: 7 } ) 50 | 51 | b1 = Block.next( b0, 52 | { from: "Flowers", to: "Ruben", what: "Tulip Admiral van Eijck", qty: 5 }, 53 | { from: "Vicent", to: "Anne", what: "Tulip Bloemendaal Sunset", qty: 3 }, 54 | { from: "Anne", to: "Julia", what: "Tulip Semper Augustus", qty: 1 }, 55 | { from: "Julia", to: "Luuk", what: "Tulip Semper Augustus", qty: 1 } ) 56 | 57 | b2 = Block.next( b1, 58 | { from: "Bloom & Blossom", to: "Daisy", what: "Tulip Admiral of Admirals", qty: 8 }, 59 | { from: "Vincent", to: "Max", what: "Tulip Bloemendaal Sunset", qty: 2 }, 60 | { from: "Anne", to: "Martijn", what: "Tulip Semper Augustus", qty: 2 }, 61 | { from: "Ruben", to: "Julia", what: "Tulip Admiral van Eijck", qty: 2 } ) 62 | ... 63 | ``` 64 | 65 | resulting in: 66 | 67 | ``` 68 | [#"Dutchgrown", :to=>"Vincent", :what=>"Tulip Bloemendaal Sunset", :qty=>10}, 76 | {:from=>"Keukenhof", :to=>"Anne", :what=>"Tulip Semper Augustus", :qty=>7}]>, 77 | #"Flowers", :to=>"Ruben", :what=>"Tulip Admiral van Eijck", :qty=>5}, 85 | {:from=>"Vicent", :to=>"Anne", :what=>"Tulip Bloemendaal Sunset", :qty=>3}, 86 | {:from=>"Anne", :to=>"Julia", :what=>"Tulip Semper Augustus", :qty=>1}, 87 | {:from=>"Julia", :to=>"Luuk", :what=>"Tulip Semper Augustus", :qty=>1}]>, 88 | #"Bloom & Blossom", :to=>"Daisy", :what=>"Tulip Admiral of Admirals", :qty=>8}, 96 | {:from=>"Vincent", :to=>"Max", :what=>"Tulip Bloemendaal Sunset", :qty=>2}, 97 | {:from=>"Anne", :to=>"Martijn", :what=>"Tulip Semper Augustus", :qty=>2}, 98 | {:from=>"Ruben", :to=>"Julia", :what=>"Tulip Admiral van Eijck", :qty=>2}]>, 99 | ... 100 | ``` 101 | 102 | 103 | ## Alternatives 104 | 105 | Anyone? Show us your tulips on the blockchain examples! 106 | 107 | 108 | ## What's a Blockchain? 109 | 110 | See the [Awesome Blockchains](https://github.com/openblockchains/awesome-blockchains) page for more. 111 | 112 | 113 | ## We <3 Tulips, Tulips, Tulips :tulip::tulip::tulip: 114 | 115 | > Tulips never lost their popularity, and growers in the west of Holland 116 | > have continued to develop new varieties to this very day. 117 | > 118 | > -- Rijksmuseum, Amsterdam 119 | 120 | 121 | 122 | 123 | ## License 124 | 125 | ![](https://publicdomainworks.github.io/buttons/zero88x31.png) 126 | 127 | The tulips on the blockchain transactions and scripts are dedicated to the public domain. 128 | Use it as you please with no restrictions whatsoever. 129 | -------------------------------------------------------------------------------- /WHATSBLOCKCHAIN.md: -------------------------------------------------------------------------------- 1 | # What's Blockchain? 2 | 3 | 4 | > Blockchain is a distributed database with a list (that is, chain) of records (that is, blocks) 5 | > linked and secured by digital fingerprints (that is, cryptho hashes). 6 | > 7 | > -- [Awesome Blockchains](https://github.com/openblockchains/awesome-blockchains) 8 | 9 | 10 | > Blockchain is a continuously growing list of records, called blocks, which are linked and secured using cryptography. 11 | > Each block typically contains a hash pointer as a link to a previous block, a timestamp and transaction data. 12 | > By design, blockchains are inherently resistant to modification of the data. 13 | > A blockchain can serve as "an open, distributed ledger that can record transactions between two parties efficiently 14 | > and in a verifiable and permanent way." 15 | > 16 | > -- [Blockchain @ Wikipedia](https://en.wikipedia.org/wiki/Blockchain) 17 | 18 | 19 | > [Blockchain is ...] a solution to the double-spending problem using a peer-to-peer network. 20 | > The network timestamps transactions by hashing them into an ongoing chain of hash-based proof-of-work, 21 | > forming a record that cannot be changed without redoing the proof-of-work. 22 | > The longest chain not only serves as proof of the sequence of events witnessed, 23 | > but proof that it came from the largest pool of CPU power... 24 | > The network itself requires minimal structure. 25 | > 26 | > -- Satoshi Nakamoto @ Bitcoin Whitepaper 27 | 28 | 29 | > Blockchain [data structure] is an ordered, back-linked list of blocks of transactions. 30 | > The blockchain can be stored as a flat file, or in a simple database. 31 | > The Bitcoin Core client stores the blockchain metadata using Google's LevelDB database. 32 | > Blocks are linked "back," each referring to the previous block in the chain. 33 | > The blockchain is often visualized as a vertical stack, with blocks layered on top of each other 34 | > and the first block serving as the foundation of the stack. 35 | > The visualization of blocks stacked on top of each other results in the use of terms such as "height" 36 | > to refer to the distance from the first block, and "top" or "tip" to refer to the most recently added block. 37 | > 38 | > Each block within the blockchain is identified by a hash, generated using the SHA256 cryptographic hash algorithm 39 | > on the header of the block. Each block also references a previous block, known as the parent block, 40 | > through the "previous block hash" field in the block header. 41 | > In other words, each block contains the hash of its parent inside its own header. 42 | > The sequence of hashes linking each block to its parent creates a chain going back all the way to the first block ever created, 43 | > known as the genesis block. 44 | > 45 | > -- [Andreas M. Antonopoulos @ Mastering Bitcoin: Programming the Open Blockchain](https://github.com/bitcoinbook/bitcoinbook/blob/second_edition/ch09.asciidoc) 46 | 47 | 48 | 49 | 50 | > Blockchain is a public database where new data are stored in a container called a block 51 | > and are added to an immutable chain (hence blockchain) with data added in the past. 52 | > In the case of Bitcoin and other cryptocurrencies, these data are groups of transactions. 53 | > But, the data can be of any type, of course. 54 | > 55 | > -- [Gerald Nash @ Let's Build the Tiniest Blockchain](https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b) 56 | 57 | 58 | > Blockchain is a public database that consists out of blocks that anyone can read. 59 | > Nothing special, but they have an interesting property: they are immutable. 60 | > Once a block has been added to the chain, it cannot be changed anymore without invalidating the rest of the chain. 61 | > 62 | > -- [Xavier Decuyper @ Writing a Tiny Blockchain in JavaScript](https://www.savjee.be/2017/07/Writing-tiny-blockchain-in-JavaScript/) 63 | 64 | 65 | > Blockchain is a distributed database with a set of rules for verifying new additions to the database. 66 | > 67 | > -- [Eric Munsing @ Build Your Own Blockchain: A Python Tutorial](http://ecomunsing.com/build-your-own-blockchain) 68 | 69 | 70 | 71 | > Blockchain is a digital ledger in which transactions made in bitcoin or another cryptocurrency 72 | > are recorded chronologically and publicly. 73 | > 74 | > -- [Google Search: Blockchain Definition](https://www.google.com/search?q=blockchain+definition) 75 | 76 | 77 | > Blockchain is an incorruptible digital ledger of economic transactions that can be programmed to record 78 | > not just financial transactions but virtually everything of value. 79 | > 80 | > -- Don & Alex Tapscott, Blockchain Revolution (2016) 81 | 82 | 83 | > Blockchain is a data structure that makes it possible to create a digital 84 | > ledger of data and share it among a network of independent parties. 85 | > 86 | > -- Tiana Laurence @ Blockchain for Dummies (2017) 87 | 88 | 89 | > Blockchain is a shared, distributed ledger that facilitates the process 90 | > of recording transactions and tracking assets in a business network. 91 | > An asset can be tangible - a house, a car, cash, land - or intangible 92 | > like intellectual property, such as patents, copyrights, or branding. 93 | > Virtually anything of value can be tracked or traded on a blockchain 94 | > network, reducing risk and cutting costs for all involved. 95 | > 96 | > -- Manav Gupta @ Blockchain for Dummies - IBM Limited Edition (2017) 97 | 98 | 99 | > Blockchain is a shared, immutable ledger for recording the history of transactions. 100 | > It fosters a new generation of transactional applications that establish trust, 101 | > accountability and transparency - from contracts to deeds to payments. 102 | > 103 | > -- [IBM Blockchain](https://ibm.com/blockchain) 104 | 105 | 106 | 107 | > Blockchain is the magic that will power all the world's financial transactions 108 | > and unlock the great decentralized database in the sky. 109 | > 110 | > -- Snake Oil Purveyors 111 | 112 | 113 | > Blockchain is a provably-immutable append-only data log with transaction validation based on asymmetric crypto, 114 | > and (optionally) a Byzantine-generals solution too! 115 | > 116 | > -- [Tim Bray @ I Don't Believe in Blockchain](https://www.tbray.org/ongoing/When/201x/2017/05/13/Not-Believing-in-Blockchain) 117 | 118 | 119 | > Blockchain is really a fairly old set of ideas - merkle hash trees, distributed databases etc. 120 | > The novelty, if any, is in a convergence of different methods and new levels of efficiency. 121 | > This is the stuff of solid, and valuable, progress. 122 | > But it isn't a revolution in governance, production or the structure of society. 123 | > 124 | > -- [Rufus Pollock @ Reflections on the Blockchain](http://rufuspollock.com/2016/07/02/reflections-on-the-blockchain/) 125 | 126 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | -------------------------------------------------------------------------------- /blockchain.rb/blockchain_with_transactions.rb: -------------------------------------------------------------------------------- 1 | ########################### 2 | # build your own blockchain from scratch in 20 lines of ruby! 3 | # 4 | # to run use: 5 | # $ ruby ./blockchain_with_transactions.rb 6 | 7 | # 8 | # transactions (hyper) ledger / book: 9 | # 10 | # from: Dutchgrown to: Vincent what: Tulip Bloemendaal Sunset qty: 10 11 | # from: Keukenhof to: Anne what: Tulip Semper Augustus qty: 7 12 | # 13 | # from: Flowers to: Ruben what: Tulip Admiral van Eijck qty: 5 14 | # from: Vicent to: Anne what: Tulip Bloemendaal Sunset qty: 3 15 | # from: Anne to: Julia what: Tulip Semper Augustus qty: 1 16 | # from: Julia to: Luuk what: Tulip Semper Augustus qty: 1 17 | # 18 | # from: Bloom & Blossom to: Daisy what: Tulip Admiral of Admirals qty: 8 19 | # from: Vincent to: Max what: Tulip Bloemendaal Sunset qty: 2 20 | # from: Anne to: Martijn what: Tulip Semper Augustus qty: 2 21 | # from: Ruben to: Julia what: Tulip Admiral van Eijck qty: 2 22 | # 23 | # from: Teleflora to: Max what: Tulip Red Impression qty: 11 24 | # from: Anne to: Naomi what: Tulip Bloemendaal Sunset qty: 1 25 | # from: Daisy to: Vincent what: Tulip Admiral of Admirals qty: 3 26 | # from: Julia to: Mina what: Tulip Admiral van Eijck qty: 1 27 | # 28 | # from: Max to: Isabel what: Tulip Red Impression qty: 2 29 | # 30 | # (source: tulips on the blockchain - public distributed (hyper) ledger 31 | # @ github.com/openblockchains/tulips ) 32 | 33 | 34 | require "digest" # for hash checksum digest function SHA256 35 | require "pp" # for pp => pretty printer 36 | 37 | 38 | class Block 39 | 40 | attr_reader :index 41 | attr_reader :timestamp 42 | attr_reader :transactions 43 | attr_reader :transactions_count 44 | attr_reader :previous_hash 45 | attr_reader :hash 46 | 47 | def initialize(index, transactions, previous_hash) 48 | @index = index 49 | @timestamp = Time.now.utc 50 | @transactions = transactions 51 | @transactions_count = transactions.size 52 | @previous_hash = previous_hash 53 | @hash = calc_hash 54 | end 55 | 56 | def calc_hash 57 | sha = Digest::SHA256.new 58 | sha.update( @index.to_s + 59 | @timestamp.to_s + 60 | @transactions_count.to_s + 61 | @transactions.to_s + 62 | @previous_hash ) 63 | sha.hexdigest 64 | end 65 | 66 | 67 | ## ruby note: the splat operator (that is, *) turns list of passed in transactions into array 68 | def self.first( *transactions ) # create genesis (big bang! first) block 69 | ## uses index zero (0) and arbitrary previous_hash ("0") 70 | Block.new( 0, transactions, "0" ) 71 | end 72 | 73 | def self.next( previous, *transactions ) 74 | Block.new( previous.index+1, transactions, previous.hash ) 75 | end 76 | 77 | end # class Block 78 | 79 | 80 | ##### 81 | ## let's get started 82 | ## build a blockchain a block at a time 83 | 84 | b0 = Block.first( 85 | { from: "Dutchgrown", to: "Vincent", what: "Tulip Bloemendaal Sunset", qty: 10 }, 86 | { from: "Keukenhof", to: "Anne", what: "Tulip Semper Augustus", qty: 7 } ) 87 | 88 | b1 = Block.next( b0, 89 | { from: "Flowers", to: "Ruben", what: "Tulip Admiral van Eijck", qty: 5 }, 90 | { from: "Vicent", to: "Anne", what: "Tulip Bloemendaal Sunset", qty: 3 }, 91 | { from: "Anne", to: "Julia", what: "Tulip Semper Augustus", qty: 1 }, 92 | { from: "Julia", to: "Luuk", what: "Tulip Semper Augustus", qty: 1 } ) 93 | 94 | b2 = Block.next( b1, 95 | { from: "Bloom & Blossom", to: "Daisy", what: "Tulip Admiral of Admirals", qty: 8 }, 96 | { from: "Vincent", to: "Max", what: "Tulip Bloemendaal Sunset", qty: 2 }, 97 | { from: "Anne", to: "Martijn", what: "Tulip Semper Augustus", qty: 2 }, 98 | { from: "Ruben", to: "Julia", what: "Tulip Admiral van Eijck", qty: 2 } ) 99 | 100 | b3 = Block.next( b2, 101 | { from: "Teleflora", to: "Max", what: "Tulip Red Impression", qty: 11 }, 102 | { from: "Anne", to: "Naomi", what: "Tulip Bloemendaal Sunset", qty: 1 }, 103 | { from: "Daisy", to: "Vincent", what: "Tulip Admiral of Admirals", qty: 3 }, 104 | { from: "Julia", to: "Mina", what: "Tulip Admiral van Eijck", qty: 1 } ) 105 | 106 | 107 | blockchain = [b0, b1, b2, b3] 108 | 109 | pp blockchain 110 | 111 | ###### 112 | # will pretty print (pp) something like: 113 | # 114 | # [#"Dutchgrown", :to=>"Vincent", :what=>"Tulip Bloemendaal Sunset", :qty=>10}, 121 | # {:from=>"Keukenhof", :to=>"Anne", :what=>"Tulip Semper Augustus", :qty=>7}], 122 | # @transactions_count=2>, 123 | # #"Flowers", :to=>"Ruben", :what=>"Tulip Admiral van Eijck", :qty=>5}, 131 | # {:from=>"Vicent", :to=>"Anne", :what=>"Tulip Bloemendaal Sunset", :qty=>3}, 132 | # {:from=>"Anne", :to=>"Julia", :what=>"Tulip Semper Augustus", :qty=>1}, 133 | # {:from=>"Julia", :to=>"Luuk", :what=>"Tulip Semper Augustus", :qty=>1}], 134 | # @transactions_count=4>, 135 | # #"Bloom & Blossom", :to=>"Daisy", :what=>"Tulip Admiral of Admirals", :qty=>8}, 143 | # {:from=>"Vincent", :to=>"Max", :what=>"Tulip Bloemendaal Sunset", :qty=>2}, 144 | # {:from=>"Anne", :to=>"Martijn", :what=>"Tulip Semper Augustus", :qty=>2}, 145 | # {:from=>"Ruben", :to=>"Julia", :what=>"Tulip Admiral van Eijck", :qty=>2}], 146 | # @transactions_count=4>, 147 | # #"Teleflora", :to=>"Max", :what=>"Tulip Red Impression", :qty=>11}, 155 | # {:from=>"Anne", :to=>"Naomi", :what=>"Tulip Bloemendaal Sunset", :qty=>1}, 156 | # {:from=>"Daisy", :to=>"Vincent", :what=>"Tulip Admiral of Admirals", :qty=>3}, 157 | # {:from=>"Julia", :to=>"Mina", :what=>"Tulip Admiral van Eijck", :qty=>1}], 158 | # @transactions_count=4>] 159 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Mining Digital Gold one Block at a Time?! • Don't Expect to Get Insanely Rich (Quick) • Tulips :tulip::tulip::tulip: (like Blockchains) are Great and Gorgeous (and will Endure) 3 | 4 | ```ruby 5 | b0 = Block.first( 6 | { from: "Dutchgrown", to: "Vincent", what: "Tulip Bloemendaal Sunset", qty: 10 }, 7 | { from: "Keukenhof", to: "Anne", what: "Tulip Semper Augustus", qty: 7 } ) 8 | 9 | b1 = Block.next( b0, 10 | { from: "Flowers", to: "Ruben", what: "Tulip Admiral van Eijck", qty: 5 }, 11 | { from: "Vicent", to: "Anne", what: "Tulip Bloemendaal Sunset", qty: 3 }, 12 | { from: "Anne", to: "Julia", what: "Tulip Semper Augustus", qty: 1 }, 13 | { from: "Julia", to: "Luuk", what: "Tulip Semper Augustus", qty: 1 } ) 14 | ... 15 | ``` 16 | 17 | (Source: [`blockchain_with_transactions.rb`](blockchain.rb/blockchain_with_transactions.rb)) 18 | 19 | 20 | # Awesome Blockchains 21 | 22 | A collection about awesome blockchains - open distributed databases w/ crypto hashes incl. git ;-). Blockchains are the new tulips :tulip::tulip::tulip:. 23 | 24 | Contents: 25 | 26 | - [Frequently Asked Questions (F.A.Q.s) & Answers](#frequently-asked-questions-faqs--answers) 27 | - [Do-It-Yourself (DIY) - Build Your Own Blockchain](#do-it-yourself-diy---build-your-own-blockchain) 28 | - [Python](#python) • [Ruby](#ruby) • [JavaScript](#javascript) • [Java](#java) • [Go](#go) 29 | - [Blockchain Articles](#blockchain-articles) 30 | - [Blockchain Books](#blockchain-books) 31 | - [Blockchain (Lite) Crypto Hash Libraries](#blockchain-lite-crypto-hash-libraries) 32 | - [Git, Git, Git - The Stupid Content Tracker with Crypto Hashes](#git-git-git---the-stupid-content-tracker-with-crypto-hashes) 33 | - [Classic Tulip Mania](#classic-tulip-mania) 34 | - [Awesome Awesomeness](#awesome-awesomeness) 35 | 36 | 37 | 38 | ## What's News? 39 | 40 | For blockchain books, see the new [**Best of Crypto Books page »**](https://openblockchains.github.io/crypto-books/) 41 | 42 | ### The Open Blockchains Book of the Year 2020 Award Goes To... 43 | 44 | ![](i/libra-shrugged.png) 45 | [**Libra Shrugged: How Facebook Tried to Take Over the Money**](https://davidgerard.co.uk/blockchain/libra/) 46 | by David Gerard, November 2020, 182 Pages -- 47 | _Introduction: Taking over the money ++ 48 | A user's guide to Libra ++ 49 | The genesis of Libra: Beller's blockchain ++ 50 | To launch a Libra: Let’s start a crypto ++ 51 | Bitcoin: why Libra is like this ++ 52 | The Libra White Papers ++ 53 | Banking the unbanked ++ 54 | The Libra Reserve plan and economic stability ++ 55 | Libra, privacy and your digital identity ++ 56 | The regulators recoil in horror ++ 57 | David Marcus before the US House and Senate ++ 58 | July to September 2019: Libra runs the gauntlet ++ 59 | October 2019: Libra's bad month ++ 60 | Mark Zuckerberg before the US House ++ 61 | November 2019: The comedown ++ 62 | Central bank digital currencies ++ 63 | Epilogue: Libra 2.0: not dead yet ++ 64 | Appendix: 2010–2013: The rise and fall of Facebook Credits_ 65 | 66 | For more about Diem (formerly Libra), see the [Awesome Diem (formerly Libra) and Move page »](https://github.com/openblockchains/awesome-diem) 67 | 68 | --- 69 | 70 | For crypto quotes, see the new [**100+ Best of Crypto Quotes - I HODL, you HODL, we HODL! - BREAKING: BITCOIN JUST BROKE $22 000! page »**](https://github.com/openblockchains/crypto-quotes) 71 | 72 | ### The Best Crypto Quote "Oracle Saying" of the Year 2020 Award Goes To... 73 | 74 | > SEC Investor Education: 75 | > - Don't understand an investment? 76 | > - Don't invest in it. 77 | 78 | Yes, but what if there's only 21 million of it? 79 | 80 | \- Trolly McTrollface 81 | 82 | 83 | 84 | ## Frequently Asked Questions (F.A.Q.s) & Answers 85 | 86 | 87 | **Q: What's a Blockchain?** 88 | 89 | A: A blockchain is a distributed database with a list (that is, chain) of records (that is, blocks) linked and secured by 90 | digital fingerprints (that is, cryptho hashes). 91 | Example from [`blockchain.rb`](blockchain.rb/blockchain.rb): 92 | 93 | ``` 94 | [#, 99 | #, 104 | #, 109 | ... 110 | ``` 111 | 112 | ![](i/blockchain-jesus.png) 113 | 114 | 115 | **Q: What's a Hash? What's a (One-Way) Crypto(graphic) Hash Digest Checksum**? 116 | 117 | A: A hash e.g. `eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743` 118 | is a small digest checksum calculated 119 | with a one-way crypto(graphic) hash digest checksum function 120 | e.g. SHA256 (Secure Hash Algorithm 256 Bits) 121 | from the data. Example from [`blockchain.rb`](blockchain.rb/blockchain.rb): 122 | 123 | ```ruby 124 | def calc_hash 125 | sha = Digest::SHA256.new 126 | sha.update( @timestamp.to_s + @previous_hash + @data ) 127 | sha.hexdigest ## returns "eb8ecbf6d5870763ae246e37539d82e37052cb32f88bb8c59971f9978e437743" 128 | end 129 | ``` 130 | 131 | A blockchain uses 132 | 133 | - the block timestamp (e.g. `1637-09-15 20:52:38`) and 134 | - the hash from the previous block (e.g. `edbd4e11e69bc399a9ccd8faaea44fb27410fe8e3023bb9462450a0a9c4caa1b`) and finally 135 | - the block data (e.g. `Transaction Data...`) 136 | 137 | to calculate the new hash digest checksum, that is, the hash 138 | e.g. `be50017ee4bbcb33844b3dc2b7c4e476d46569b5df5762d14ceba9355f0a85f4`. 139 | 140 | 141 | **Q: What's a Merkle Tree?** 142 | 143 | A: A Merkle tree is a hash tree named after Ralph Merkle who patented the concept in 1979 144 | (the patent expired in 2002). A hash tree is a generalization of hash lists or hash chains where every leaf node (in the tree) is labelled with a data block and every non-leaf node (in the tree) 145 | is labelled with the crypto(graphic) hash of the labels of its child nodes. For more see the [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree) Wikipedia Article. 146 | 147 | Note: By adding crypto(graphic) hash functions you can "merkelize" any data structure. 148 | 149 | 150 | **Q: What's a Merkelized DAG (Directed Acyclic Graph)?** 151 | 152 | A: It's a blockchain secured by crypto(graphic) hashes that uses a directed acyclic graph data structure (instead of linear "classic" linked list). 153 | 154 | Note: Git uses merkelized dag (directed acyclic graph)s for its blockchains. 155 | 156 | 157 | **Q: Is the Git Repo a Blockchain?** 158 | 159 | A: Yes, every branch in the git repo is a blockchain. 160 | The "classic" Satoshi-blockchain is like a git repo with a single master branch (only). 161 | 162 | 163 | 164 | ## Do-It-Yourself (DIY) - Build Your Own Blockchain 165 | 166 | ![](i/fake-dilbert-blockchain.png) 167 | 168 | 169 | [Python](#python) • 170 | [Ruby](#ruby) • 171 | [JavaScript](#javascript) • 172 | [Java](#java) • 173 | [Go](#go) 174 | 175 | 176 | ### Python 177 | 178 | **Let's Build the Tiniest Blockchain in Python Series** by Gerald Nash 179 | 180 | - [**Let's Build the Tiniest Blockchain In Less Than 50 Lines of Python (Part 1)**](https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b), July 2016 181 | - [**Let's Make the Tiniest Blockchain Bigger With More Lines of Python (Part 2)**](https://medium.com/crypto-currently/lets-make-the-tiniest-blockchain-bigger-ac360a328f4d), July 2016 182 | 183 | 184 | 185 | [**Build Your Own Blockchain: A Python Tutorial**](http://ecomunsing.com/build-your-own-blockchain) 186 | by Eric Munsing, March 2017, [(Source)](https://github.com/emunsing/tutorials/blob/master/BuildYourOwnBlockchain.ipynb) 187 | 188 | 189 | [**Learn Blockchains by Building One (in Python)**](https://hackernoon.com/learn-blockchains-by-building-one-117428612f46) 190 | by Daniel van Flymen, September 2017, [(Source)](https://github.com/dvf/blockchain) -- The fastest way to learn how Blockchains work is to build one 191 | 192 | 193 | **Build Your Own Blockchain (in Python 3) Series** by Jack Schultz, [(Source)](https://github.com/jackschultz/jbc) 194 | 195 | - [**Part 1: Creating, Storing, Syncing, Displaying, Mining, and Proving Work**](https://bigishdata.com/2017/10/17/write-your-own-blockchain-part-1-creating-storing-syncing-displaying-mining-and-proving-work/), October 2017 196 | - [**Part 2: Syncing Chains From Different Nodes**](https://bigishdata.com/2017/10/27/build-your-own-blockchain-part-2-syncing-chains-from-different-nodes/), October 2017 197 | - [**Part 3: Writing Nodes that Mine and Talk**](https://bigishdata.com/2017/11/02/build-your-own-blockchain-part-3-writing-nodes-that-mine/), November 2017 198 | 199 | 200 | 201 | [**A Practical Introduction to Blockchain with Python**](http://adilmoujahid.com/posts/2018/03/intro-blockchain-bitcoin-python/) 202 | by Adil Moujahid, March 2018, [(Source)](https://github.com/adilmoujahid/blockchain-python-tutorial) 203 | 204 | 205 | ### Ruby 206 | 207 | [**How Does Bitcoin Force Consensus Among Byzantine Generals?**](http://www.akitaonrails.com/2017/11/01/how-does-bitcoin-force-consensus-among-byzantine-generals) by Fabio Akita, November 2017 208 | 209 | [**blockchain-lite - Build your own blockchains with crypto hashes; revolutionize the world with blockchains, blockchains, blockchains one block at a time!**](https://planetruby.github.io/calendar/advent2017/01-blockchain-lite) by Gerald Bauer, Ruby Advent Calendar 2017 / Day 1, December 2017 210 | 211 | [**merkletree library - Build Your Own Crypto Hash Trees; Grow Your Own Money on Trees**](https://planetruby.github.io/calendar/advent2017/19-merkletree.html) by Gerald Bauer, Ruby Advent Calendar 2017 / Day 19, December 2017 212 | 213 | [**centralbank command line tool (and library) - Print Your Own Money / Cryptocurrency; Run Your Own Federated Central Bank Nodes on the Blockchain Peer-to-Peer over HTTP**](https://planetruby.github.io/calendar/advent2017/24-centralbank.html) by Gerald Bauer, Ruby Advent Calendar 2017 / Day 24, December 2017 214 | 215 | [**A guide to building a blockchain & cryptocurrency from scratch**](https://antoinefink.com/building-a-blockchain-and-cryptocurrency-in-ruby) [(Source)](https://github.com/antoinefink/melon) by Antoine Fink, April 2021 216 | 217 | 218 | ### Crystal 219 | 220 | [**Write your own blockchain and Proof-of-Work (PoW) algorithm using Crystal**](https://medium.com/@bradford_hamilton/write-your-own-blockchain-and-pow-algorithm-using-crystal-d53d5d9d0c52) by Bradford Lamson-Scribner, May 2018, 221 | [(Source)](https://github.com/bradford-hamilton/crystal-blockchain) 222 | 223 | 224 | ### JavaScript 225 | 226 | [**Writing a Tiny Blockchain in JavaScript**](https://www.savjee.be/2017/07/Writing-tiny-blockchain-in-JavaScript/) 227 | by Xavier Decuyper, July 2017 228 | 229 | [**Node.js Blockchain Imlementation: BrewChain: Chain+WebSockets+HTTP Server**](http://www.darrenbeck.co.uk/blockchain/nodejs/nodejscrypto/) by Darren Beck, November 2017, [(Source)](https://github.com/dbbddb/BrewChain) -- Protecting the tea making ledger from unscrupulous colleagues 230 | 231 | [**Build your own Blockchain in Javascript/Visualization of Blockchains**](https://github.com/nambrot/blockchain-in-js) by Nam Chu Hoai, January 2018 232 | 233 | 234 | ### TypeScript 235 | 236 | [**Naivecoin: a tutorial for building a cryptocurrency**](https://lhartikk.github.io) by Lauri Hartikka, [(Source)](https://github.com/lhartikk/naivecoin) 237 | 238 | 239 | ### Java 240 | 241 | [**Creating Your First Blockchain with Java, Part 1**](https://medium.com/programmers-blockchain/create-simple-blockchain-java-tutorial-from-scratch-6eeed3cb03fa) by Kass, December 2017, [(Source)](https://github.com/CryptoKass/NoobChain-Tutorial-Part-1) 242 | 243 | ### Kotlin 244 | 245 | [**Let's implement a cryptocurrency in Kotlin**](https://medium.com/@vasilyf/lets-implement-a-cryptocurrency-in-kotlin-part-1-blockchain-8704069f8580) by Vasily Fomin, July 2018, 246 | [(Source)](https://github.com/VasilyFomin/kCoin) 247 | 248 | 249 | ### SQL 250 | 251 | [**Blockchain by Example in SQL Server**](https://medium.com/@benjaminsky/blockchain-by-example-in-sql-server-8376b410128) by Benjamin Campbell, December 2017, [(Source)](https://github.com/benjaminsky/BlockchainMessenger) 252 | 253 | 254 | ### Rust 255 | 256 | **Building Blockchain in Rust Series** by Jacob Lindahl, GeekLaunch, [(Source)](https://github.com/GeekLaunch/blockchain-rust), [(Slide Decks in PDF)](https://github.com/GeekLaunch/slides) 257 | - [**Part 1: Blocks and Hashing**](https://medium.com/geeklaunch/blockchain-in-rust-01-blocks-hashing-4192f2265d3d), January 2019 258 | - [**Part 2: Mining**](https://medium.com/geeklaunch/blockchain-in-rust-02-mining-companion-guide-9106b7a7696d), January 2019 259 | - [**Part 3: Chains and Checks**](https://medium.com/geeklaunch/blockchain-in-rust-03-chains-checks-companion-guide-2714e1a76654), January 2019 260 | 261 | ### Go 262 | 263 | **Building Blockchain in Go Series** by Ivan Kuznetsov, [(Source)](https://github.com/Jeiwan/blockchain_go) 264 | 265 | - [**Part 1: Basic Prototype**](https://jeiwan.cc/posts/building-blockchain-in-go-part-1/), August 2017 266 | - [**Part 2: Proof-of-Work**](https://jeiwan.cc/posts/building-blockchain-in-go-part-2/), August 2017 267 | - [**Part 3: Persistence and CLI**](https://jeiwan.cc/posts/building-blockchain-in-go-part-3/), August 2017 268 | - [**Part 4: Transactions 1**](https://jeiwan.cc/posts/building-blockchain-in-go-part-4/), September 2017 269 | - [**Part 5: Addresses**](https://jeiwan.cc/posts/building-blockchain-in-go-part-5/), September 2017 270 | - [**Part 6: Transactions 2**](https://jeiwan.cc/posts/building-blockchain-in-go-part-6/), September 2017 271 | - [**Part 7: Network**](https://jeiwan.cc/posts/building-blockchain-in-go-part-7/), October 2017 272 | 273 | 274 | 275 | Blockchain Series in Go by by Coral Health [(Source)](https://github.com/mycoralhealth/blockchain-tutorial) 276 | 277 | - [**Code your own blockchain in less than 200 lines of Go!**](https://medium.com/@mycoralhealth/code-your-own-blockchain-in-less-than-200-lines-of-go-e296282bcffc) by Coral Health, January 2018 278 | - [**Part 2: Networking — Code your own blockchain in less than 200 lines of Go!**](https://medium.com/@mycoralhealth/part-2-networking-code-your-own-blockchain-in-less-than-200-lines-of-go-17fe1dad46e1) by Coral Health, February 2018 279 | - [**Code your own blockchain mining algorithm in Go!**](https://medium.com/@mycoralhealth/code-your-own-blockchain-mining-algorithm-in-go-82c6a71aba1f) by Coral Health, March 2018 280 | 281 | 282 | 288 | 289 | 290 | ### Talk Notes 291 | 292 | - [**Blockchain! Blockchain! Blockchain! - Build Your Own Blockchains in JavaScript from Zero (Scratch)**](https://github.com/geraldb/talks/blob/master/blockchain.md) by Gerald Bauer, Vienna.js, September 2017 293 | - [**Blockchain! Blockchain! Blockchain! - Build Your Own Blockchains in Ruby from Zero (Scratch)**](https://github.com/geraldb/talks/blob/master/blockchain_ruby.md) by Gerald Bauer, Vienna.rb, Dezember 2017 294 | - [**Blockchain vs (Hyper) Ledger -- Inside (Hyper) Ledger Lite - Add Transactions One Block at a Time and Balance the Accounts (Books)**](https://github.com/geraldb/talks/blob/master/hyperledger.md) by Gerald Bauer, Hyperledger Vienna, March 2018 295 | - [**Blockchain! Blockchain! Blockchain! - Build Your Own Blockchains in Go from Zero (Scratch)**](https://github.com/geraldb/talks/blob/master/blockchain_go.md) by Gerald Bauer, Vienna.go, April 2018 296 | 297 | 298 | ### More 299 | 300 | See [**Build your own Blockchain / Cryptocurrency**](https://github.com/danistefanovic/build-your-own-x#build-your-own-blockchain--cryptocurrency) @ Build your own (insert technology here) 301 | 302 | 303 | 304 | 305 | ### Samples 306 | 307 | #### Blockchain from Scratch - Ruby Version 308 | 309 | ```ruby 310 | class Block 311 | 312 | attr_reader :timestamp 313 | attr_reader :data 314 | attr_reader :previous_hash 315 | attr_reader :hash 316 | 317 | def initialize(data, previous_hash) 318 | @timestamp = Time.now 319 | @data = data 320 | @previous_hash = previous_hash 321 | @hash = calc_hash 322 | end 323 | 324 | def self.first( data="Genesis" ) # create genesis (big bang! first) block 325 | ## note: uses all zero for previous_hash ("0") 326 | Block.new( data, "0000000000000000000000000000000000000000000000000000000000000000" ) 327 | end 328 | 329 | def self.next( previous, data="Transaction Data..." ) 330 | Block.new( data, previous.hash ) 331 | end 332 | 333 | private 334 | 335 | def calc_hash 336 | sha = Digest::SHA256.new 337 | sha.update( @timestamp.to_s + @previous_hash + @data ) 338 | sha.hexdigest 339 | end 340 | 341 | end # class Block 342 | 343 | 344 | ##### 345 | ## let's get started 346 | ## build a blockchain a block at a time 347 | 348 | b0 = Block.first( "Genesis" ) 349 | b1 = Block.next( b0, "Transaction Data..." ) 350 | b2 = Block.next( b1, "Transaction Data......" ) 351 | b3 = Block.next( b2, "More Transaction Data..." ) 352 | 353 | blockchain = [b0, b1, b2, b3] 354 | 355 | pp blockchain 356 | 357 | ``` 358 | 359 | (Source: [`blockchain.rb`](blockchain.rb/blockchain.rb)) 360 | 361 | will pretty print (pp) something like: 362 | 363 | ``` 364 | [#, 369 | #, 374 | #, 379 | #] 384 | ``` 385 | 386 | 387 | Comments from the [reddit ruby posting](https://www.reddit.com/r/ruby/comments/70c30f/build_your_own_blockchain_in_20_lines_of_ruby/): 388 | 389 | > Wait, so a blockchain is just a linked list? 390 | > 391 | >> No. A linked list is only required to have a reference to the previous element, a block must 392 | >> have an identifier depending on the previous block's identifier, meaning that you cannot 393 | >> replace a block without recomputing every single block that comes after. 394 | >> In this implementation that happens as the previous digest is input in the calc_hash method. 395 | 396 | 397 | 398 | **What about Proof of Work / Waste?** 399 | 400 | Let's add a proof of work / waste to the blockchain. In the classic blockchain you have to compute a block hash that starts with leading zeros (`00`). The more leading zeros the harder (more difficult) to compute. Let's keep it easy to compute with two leading zeros (`00`), that is, 16^2 = 256 possibilites (^1,2). Three leading zeros (`000`) would be 16^3 = 4_096 possibilites and four zeros (`0000`) would be 16^4 = 65_536 and so on. 401 | 402 | (^1): 16 possibilties because it's a hex or hexadecimal or base 16 number, that is, `0` `1` `2` `3` `4` `6` `7` `8` `9` `a` (10) `b` (11) `c` (12) `d` (13) `e` (14) `f` (15). 403 | 404 | (^2): A random secure hash algorithm needs on average 256 tries (might be lets say 305 tries, for example, because it's NOT a perfect statistic distribution of possibilities). 405 | 406 | 407 | Example: 408 | 409 | ```ruby 410 | def compute_hash_with_proof_of_work( difficulty="00" ) 411 | nonce = 0 412 | loop do 413 | hash = calc_hash_with_nonce( nonce ) 414 | if hash.start_with?( difficulty ) 415 | return [nonce,hash] ## bingo! proof of work if hash starts with leading zeros (00) 416 | else 417 | nonce += 1 ## keep trying (and trying and trying) 418 | end 419 | end 420 | end 421 | 422 | def calc_hash_with_nonce( nonce=0 ) 423 | sha = Digest::SHA256.new 424 | sha.update( nonce.to_s + @timestamp.to_s + @previous_hash + @data ) 425 | sha.hexdigest 426 | end 427 | ``` 428 | 429 | (Source: [`blockchain_with_proof_of_work.rb`](blockchain.rb/blockchain_with_proof_of_work.rb)) 430 | 431 | Let's rerun the sample with the proof of work machinery added. 432 | Now the sample will pretty print (pp) something like: 433 | 434 | ``` 435 | [#, 441 | #, 447 | #, 453 | #] 459 | ``` 460 | 461 | See the difference? All hashes now start with leading zeros (`00`) and the nonce is the random "lucky number" 462 | that makes it happen. That's the magic behind the proof of work. 463 | 464 | 465 | ##### Blockchain from Scratch - JavaScript Version 466 | 467 | ```js 468 | class Block { 469 | 470 | constructor(data, previousHash) { 471 | this.timestamp = new Date() 472 | this.data = data 473 | this.previousHash = previousHash 474 | this.hash = this.calcHash() 475 | } 476 | 477 | calcHash() { 478 | var sha = SHA256.create() 479 | sha.update( this.timestamp.toString() + this.previousHash + this.data ) 480 | return sha.hex() 481 | } 482 | 483 | static first( data="Genesis" ) { // create genesis (big bang! first) block 484 | // uses all-zero previousHash 485 | return new Block( data, "0000000000000000000000000000000000000000000000000000000000000000" ) 486 | } 487 | 488 | static next( previous, data="Transaction Data..." ) { 489 | return new Block( data, previous.hash ) 490 | } 491 | } 492 | 493 | 494 | ////// 495 | // let's get started 496 | // build a blockchain a block at a time 497 | 498 | b0 = Block.first( "Genesis" ) 499 | b1 = Block.next( b0, "Transaction Data..." ) 500 | b2 = Block.next( b1, "Transaction Data......" ) 501 | b3 = Block.next( b2, "More Transaction Data..." ) 502 | 503 | 504 | blockchain = [b0, b1, b2, b3] 505 | 506 | console.log( blockchain ) 507 | ``` 508 | 509 | (Source: [`blockchain.js`](blockchain.js/blockchain.js)) 510 | 511 | will log something like: 512 | 513 | ``` 514 | [ Block { 515 | timestamp : 1637-09-18 08:25:54, 516 | data : 'Genesis', 517 | previousHash : '0000000000000000000000000000000000000000000000000000000000000000', 518 | hash : 'c396de4c03ddb5275661982adc75ce5fc5905d2a2457d1266c74436c1f3c50f1' }, 519 | Block { 520 | timestamp : 1637-09-18 08:35:54, 521 | data : 'Transaction Data...', 522 | previousHash : 'c396de4c03ddb5275661982adc75ce5fc5905d2a2457d1266c74436c1f3c50f1', 523 | hash : '493131e09c069645c82795c96e4715cea0f5558be514b5096d853a5b9899154a' }, 524 | Block { 525 | timestamp : 1637-09-18 08:45:54, 526 | data : 'Transaction Data......', 527 | previousHash : '493131e09c069645c82795c96e4715cea0f5558be514b5096d853a5b9899154a', 528 | hash : '97aa3cb5052615d60ff8e6b41bef606562588c4874f011970ac2f218e2f0f4a8' }, 529 | Block { 530 | timestamp : 1637-09-18 08:55:54, 531 | data : 'More Transaction Data...', 532 | previousHash : '97aa3cb5052615d60ff8e6b41bef606562588c4874f011970ac2f218e2f0f4a8', 533 | hash : 'e10e020f832e46c2b60e1c3c0412bd370b2fde5f0f782c16eb87d0313ea0d3a3' } ] 534 | ``` 535 | 536 | 537 | 538 | ## Blockchain Articles 539 | 540 | [**Reflections on the Blockchain**](http://rufuspollock.com/2016/07/02/reflections-on-the-blockchain) by Rufus Pollock (Open Knowledge Foundation), July 2016 -- 541 | _The DAO: Code is not Law – and It’s Dangerous to Think So ++ 542 | The Internet changed the world - surely the Blockchain will too? ++ 543 | Gold-rush or Internet-rush? ++ 544 | Governance Matters in Bitcoin ++ 545 | The Myth of a Costless, Ownerless Network ++ 546 | Lessons from History_ 547 | 548 | [**On the Dangers of a Blockchain Monoculture**](https://tonyarcieri.com/on-the-dangers-of-a-blockchain-monoculture) by Tony Arcieri, January 2016 -- 549 | _The Bitcoin blockchain: the world's worst database ++ 550 | Next-generation protocols ++ 551 | Decentralized ledger protocols ++ 552 | Bitcoin-NG ++ 553 | Blockchain! Blockchain! Blockchain! ++ 554 | The great decentralized database in the sky_ 555 | 556 | 557 | [**I Don’t Believe in Blockchain**](https://www.tbray.org/ongoing/When/201x/2017/05/13/Not-Believing-in-Blockchain) by Tim Bray, May 2017 558 | 559 | 560 | [**Minimum Viable Blockchain**](https://www.igvita.com/2014/05/05/minimum-viable-block-chain/) by Ilya Grigorik, May 2014 -- 561 | _Securing transactions with triple-entry bookkeeping ++ 562 | Securing transactions with PKI ++ 563 | Balance = Σ(receipts) ++ 564 | Multi-party transfers & verification ++ 565 | Double-spending and distributed consensus - 566 | Requirements for a distributed consensus network; 567 | Protecting the network from Sybil attacks; 568 | Proof-of-work as a participation requirement ++ 569 | Building the minimum viable blockchain - 570 | Adding "blocks" & transaction fee incentives; 571 | Racing to claim the transaction fees; 572 | Resolving chain conflicts; 573 | Blocks are never final ++ 574 | Properties of the (minimum viable) blockchain_ 575 | 576 | [**Blockchains by analogies and applications: How blockchain compares to Git, Raft, and other technologies.**](https://www.oreilly.com/ideas/blockchains-by-analogies-and-applications) 577 | by Kieren James-Lubin, January 2016 -- 578 | _Blockchains are databases ++ 579 | Understanding transactions ++ 580 | Persistent, replicated databases (related technology: Git) ++ 581 | Peer-to-peer networks (related technology: BitTorrent) ++ 582 | Distributed consensus (related technology: distributed databases, Raft) ++ 583 | Minting new coins (mining) ++ 584 | Embedded identities (related technology: TLS) ++ 585 | Smart contracts: Like SQL expressions & triggers ++ 586 | What can we really do with blockchains?_ 587 | 588 | 589 | 590 | ## Blockchain Books 591 | 592 | [**Attack of the 50 Foot Blockchain: Bitcoin, Blockchain, Ethereum & Smart Contracts**](https://davidgerard.co.uk/blockchain/table-of-contents/) by David Gerard, London, 2017 -- 593 | _What is a bitcoin? ++ 594 | The Bitcoin ideology ++ 595 | The incredible promises of Bitcoin! ++ 596 | Early Bitcoin: the rise to the first bubble ++ 597 | How Bitcoin mining centralised ++ 598 | Who is Satoshi Nakamoto? ++ 599 | Spending bitcoins in 2017 ++ 600 | Trading bitcoins in 2017: the second crypto bubble ++ 601 | Altcoins ++ 602 | Smart contracts, stupid humans ++ 603 | Business bafflegab, but on the Blockchain ++ 604 | Case study: Why you can’t put the music industry on a blockchain_ 605 | 606 | 607 | [**Mastering Bitcoin - Programming the Open Blockchain**](https://github.com/bitcoinbook/bitcoinbook/blob/second_edition/ch09.asciidoc) 2nd Edition, 608 | by Andreas M. Antonopoulos, 2017 - FREE (Online Source Version) -- 609 | _What Is Bitcoin? ++ 610 | How Bitcoin Works ++ 611 | Bitcoin Core: The Reference Implementation ++ 612 | Keys, Addresses ++ 613 | Wallets ++ 614 | Transactions ++ 615 | Advanced Transactions and Scripting ++ 616 | The Bitcoin Network ++ 617 | The Blockchain ++ 618 | Mining and Consensus ++ 619 | Bitcoin Security ++ 620 | Blockchain Applications_ 621 | 622 | --- 623 | 624 | ![](i/trolly-ponzi.png) 625 | 626 | **BEWARE: Bitcoin is a gigantic ponzi scheme¹. 627 | To the moon!? The new gold standard!? 628 | Do NOT "invest" trying to get-rich-quick HODLing. 629 | Why not? The bitcoin code is archaic and out-of-date. 630 | Burn, baby, burn! Proof-of-work / waste is a global 631 | energy environmental disaster 632 | using 300 kW/h per bitcoin transaction (!) that's about 179 kilograms of CO₂ emissions². 633 | Programmable money (or the internet of value) 634 | for all future generations with (bitcoin) script 635 | without loops and jumps (gotos) and all "stateless"!? LOL.** 636 | 637 | ¹: (Source: [Best of Bitcoin Maximalist - Scammers, Morons, Clowns, Shills & BagHODLers - Inside The New New Crypto Ponzi Economics](https://bitsblocks.github.io/bitcoin-maximalist)) 638 | 639 | ²: Assuming let's say 0.596 kilograms of CO₂ per kW/h 640 | (that's the energy efficiency in Germany) that's 641 | about 179 kilograms of CO₂ per bitcoin transaction (300 kW/h × 0.596 kg). For more insights see the [Bitcoin Energy Consumption Index](https://digiconomist.net/bitcoin-energy-consumption). 642 | 643 | --- 644 | 645 | 646 | [**Programming Bitcoin from Scratch**](https://github.com/jimmysong/programmingbitcoin) by Jimmy Song, 2019 - FREE (Online Source Version) -- _[Chapter 6 - Script](https://github.com/jimmysong/programmingbitcoin/blob/master/ch06.asciidoc) - How Script Works • Example Operations • Parsing the Script Fields • Combining the Script Fields • Standard Scripts • p2pk • Problems with p2pk • Solving the Problems with p2pkh • Scripts Can Be Arbitrarily Constructed • Conclusion ++_ 647 | _[Chapter 8 - Pay-to-Script Hash](https://github.com/jimmysong/programmingbitcoin/blob/master/ch08.asciidoc) - Bare Multisig • Coding OP_CHECKMULTISIG • Problems with Bare Multisig • Pay-to-Script-Hash (p2sh) • Coding p2sh • Conclusion ++_ 648 | _[Chapter 13 - Segregated Witness](https://github.com/jimmysong/programmingbitcoin/blob/master/ch13.asciidoc) - Pay-to-Witness-Pubkey-Hash (p2wpkh) • p2wpkh Transactions • p2sh-p2wpkh • Coding p2wpkh and p2sh-p2wpkh • Pay-to-Witness-Script-Hash (p2wsh) • p2sh-p2wsh • Coding p2wsh and p2sh-p2wsh • Other Improvements • Conclusion_ 649 | 650 | 651 | [**Programming Bitcoin Script Transaction (Crypto) Contracts Step-by-Step ( Beta / Rough Draft )**](https://github.com/openblockchains/programming-bitcoin-script) 652 | by Gerald Bauer et al, 2019 - FREE (Online Version) -- 653 | _Let's start with building your own bitcoin stack machine from zero / scratch and let's run your own bitcoin ops (operations)..._ 654 | 655 | 656 | [**Programming Blockchains in Ruby from Scratch Step-by-Step Starting w/ Crypto Hashes... ( Beta / Rough Draft )**](https://github.com/yukimotopress/programming-blockchains-step-by-step) 657 | by Gerald Bauer et al, 2018 - FREE (Online Version) -- 658 | _(Crypto) Hash ++ 659 | (Crypto) Block ++ 660 | (Crypto) Block with Proof-of-Work ++ 661 | Blockchain! Blockchain! Blockchain! ++ 662 | Blockchain Broken? ++ 663 | Timestamping ++ 664 | Mining, Mining, Mining - What's Your Hash Rate? ++ 665 | Bitcoin, Bitcoin, Bitcoin ++ 666 | (Crypto) Block with Transactions (Tx)_ 667 | 668 | [**Mastering Ethereum - Building Contract Services and Decentralized Apps on the Blockchain**](https://github.com/ethereumbook/ethereumbook) - 669 | by Andreas M. Antonopoulos, Gavin Wood, 2018 - FREE (Online Source Version) 670 | _What is Ethereum ++ 671 | Introduction ++ 672 | Ethereum Clients ++ 673 | Ethereum Testnets ++ 674 | Keys and Addresses ++ 675 | Wallets ++ 676 | Transactions ++ 677 | Contract Services ++ 678 | Tokens ++ 679 | Oracles ++ 680 | Accounting & Gas ++ 681 | EVM (Ethereum Virtual Machine) ++ 682 | Consensus ++ 683 | DevP2P (Peer-To-Peer) Protocol ++ 684 | Dev Tools and Frameworks ++ 685 | Decentralized Apps ++ 686 | Ethereum Standards (EIPs/ERCs)_ 687 | 688 | 689 | [**Building Decentralized Apps on the Ethereum Blockchain**](https://www.manning.com/books/building-ethereum-dapps) by Roberto Infante, 2018 - FREE chapter 1 -- 690 | _Understanding decentralized applications ++ 691 | The Ethereum blockchain ++ 692 | Building contract services in (JavaScript-like) Solidity ++ 693 | Running contract services on the Ethereum blockchain ++ 694 | Developing Ethereum Decentralized apps with Truffle ++ 695 | Best design and security practice_ 696 | 697 | [**Programming Crypto Blockchain Contracts Step-by-Step Book / Guide ( Beta / Rough Draft )**](https://github.com/openblockchains/programming-cryptocontracts) by Gerald Bauer et al, 2019 - FREE (Online Version) -- 698 | _Let's Start with Ponzi & Pyramid Schemes. Run Your Own Lotteries, Gambling Casinos and more on the Blockchain World Computer..._ 699 | 700 | 701 | [**Programming Cryptocurrencies and Blockchains in Ruby ( Beta / Rough Draft )**](http://yukimotopress.github.io/blockchains) 702 | by Gerald Bauer et al, 2018 - FREE (Online Version) @ Yuki & Moto Press Bookshelf -- 703 | _Digital $$$ Alchemy - What's a Blockchain? - 704 | How-To Turn Digital Bits Into $$$ or €€€? • 705 | Decentralize Payments. Decentralize Transactions. Decentralize Blockchains. • 706 | The Proof of the Pudding is ... The Bitcoin (BTC) Blockchain(s) 707 | ++ 708 | Building Blockchains from Scratch - 709 | A Blockchain in Ruby in 20 Lines! A Blockchain is a Data Structure • 710 | What about Proof-of-Work? What about Consensus? • 711 | Find the Lucky Number - Nonce == Number Used Once 712 | ++ 713 | Adding Transactions - 714 | The World's Worst Database - Bitcoin Blockchain Mining • 715 | Tulips on the Blockchain! Adding Transactions 716 | ++ 717 | Blockchain Lite - 718 | Basic Blocks • 719 | Proof-of-Work Blocks • 720 | Transactions 721 | ++ 722 | Merkle Tree - 723 | Build Your Own Crypto Hash Trees; Grow Your Own Money on Trees • 724 | What's a Merkle Tree? • 725 | Transactions 726 | ++ 727 | Central Bank - 728 | Run Your Own Federated Central Bank Nodes on the Blockchain Peer-to-Peer over HTTP • 729 | Inside Mining - Printing Cryptos, Cryptos, Cryptos on the Blockchain 730 | ++ 731 | Awesome Crypto 732 | ++ 733 | Case Studies - Dutch Gulden • Shilling • CryptoKitties (and CryptoCopycats)_ 734 | 735 | 736 | 737 | [**Blockchain for Dummies, IBM Limited Edition**](https://www.ibm.com/blockchain/what-is-blockchain.html) by Manav Gupta, 2017 - FREE (Digital Download w/ Email) -- 738 | _Grasping Blockchain Fundamentals ++ 739 | Taking a Look at How Blockchain Works ++ 740 | Propelling Business with Blockchains ++ 741 | Blockchain in Action: Use Cases ++ 742 | Hyperledger, a Linux Foundation Project ++ 743 | Ten Steps to Your First Blockchain application_ 744 | 745 | 746 | [**Get Rich Quick "Business Blockchain" Bible - The Secrets of Free Easy Money**](https://github.com/bitsblocks/get-rich-quick-bible), 2018 - FREE -- 747 | _Step 1: Sell hot air. How? ++ 748 | Step 2: Pump up your tokens. How? ++ 749 | Step 3: Revolutionize the World. How?_ 750 | 751 | 752 | [**Best of Bitcoin Maximalist - Scammers, Morons, Clowns, Shills & BagHODLers - Inside The New New Crypto Ponzi Economics**](https://github.com/bitsblocks/bitcoin-maximalist) by Trolly McTrollface, et al, 2018 - FREE 753 | 754 | [**Crypto Facts - Decentralize Payments - Efficient, Low Cost, Fair, Clean - True or False?**](https://github.com/bitsblocks/crypto-facts) by Nouriel Roubini, David Gerard, et al, 2018 - FREE 755 | 756 | [**Crypto is the Mother of All Scams and (Now Busted) Bubbles - While Blockchain Is The Most Over-Hyped Technology Ever, No Better than a Spreadsheet/Database**](https://github.com/bitsblocks/crypto-bubbles) by Nouriel Roubini, 2018 - FREE 757 | 758 | [**IslandCoin White Paper - A Pen and Paper Cash System - How to Run a Blockchain on a Deserted Island**](https://github.com/bitsblocks/islandcoin-whitepaper) 759 | by Tal Kol -- 760 | _Motivation ++ 761 | Consensus ++ 762 | Transaction and Block Specification - 763 | Transaction format • 764 | Block format • 765 | Genesis block ++ 766 | References_ 767 | 768 | 769 | 770 | 771 | ## Blockchain (Lite) Crypto Hash Libraries 772 | 773 | [Ruby](#ruby) • 774 | [JavaScript](#javascript) 775 | 776 | 777 | ### Ruby 778 | 779 | **blockchain.lite** (github: [openblockchains/blockchain.lite.rb](https://github.com/openblockchains/blockchain.lite.rb), 780 | gem: [blockchain-lite](https://rubygems.org/gems/blockchain-lite)) - 781 | build your own blockchain with crypto hashes - 782 | revolutionize the world with blockchains, blockchains, blockchains one block at a time 783 | 784 | ```ruby 785 | require 'blockchain-lite' 786 | 787 | b0 = Block.first( "Genesis" ) 788 | b1 = Block.next( b0, "Transaction Data..." ) 789 | b2 = Block.next( b1, "Transaction Data......" ) 790 | b3 = Block.next( b2, "More Transaction Data..." ) 791 | 792 | blockchain = [b0, b1, b2, b3] 793 | 794 | pp blockchain 795 | ``` 796 | 797 | will pretty print (pp) something like: 798 | 799 | ``` 800 | [#, 805 | #, 810 | ... 811 | ``` 812 | 813 | 814 | ### JavaScript 815 | 816 | **blockchain.lite** (github: [openblockchains/blockchain.lite.js](https://github.com/openblockchains/blockchain.lite.js), 817 | npm: [blockchain-lite](https://www.npmjs.com/package/blockchain-lite)) - 818 | build your own blockchain with crypto hashes - 819 | revolutionize the world with blockchains, blockchains, blockchains one block at a time 820 | 821 | ```js 822 | const Blocks = require( "blockchain-lite" ) 823 | 824 | // use basic block 825 | let Block = Blocks.basic 826 | 827 | let b0 = Block.first( 'Genesis' ) 828 | let b1 = Block.next( b0, 'Transaction Data...' ) 829 | let b2 = Block.next( b1, 'Transaction Data......' ) 830 | let b3 = Block.next( b2, 'More Transaction Data...' ) 831 | 832 | let blockchain = [b0, b1, b2, b3] 833 | 834 | console.log( blockchain ) 835 | ``` 836 | 837 | will log something like: 838 | 839 | ``` 840 | [ Block { 841 | timestamp: 2017-09-25 17:03:38, 842 | data: 'Genesis', 843 | previousHash: '0000000000000000000000000000000000000000000000000000000000000000', 844 | hash: '08f4fa71628c5bc6b430228738bc8c41afaf508ece0b1cf9c9cac53d02e11829' }, 845 | Block { 846 | timestamp: 2017-09-25 17:13:38, 847 | data: 'Transaction Data...', 848 | previousHash: '08f4fa71628c5bc6b430228738bc8c41afaf508ece0b1cf9c9cac53d02e11829', 849 | hash: '740a4aeb3441484c96d1e7f63d31b716220ccee3b6fe94547cae2afbb6010626' }, 850 | Block { 851 | timestamp: 2017-09-25 17:23:38, 852 | data: 'Transaction Data......', 853 | previousHash: '740a4aeb3441484c96d1e7f63d31b716220ccee3b6fe94547cae2afbb6010626', 854 | hash: '28b6892a069e2ff7f1c3128ab495d7cd9b9b1636a51a7f69db93a14b1ee6b1a7' }, 855 | Block { 856 | timestamp: 2017-09-25 17:33:38, 857 | data: 'More Transaction Data...', 858 | previousHash: '28b6892a069e2ff7f1c3128ab495d7cd9b9b1636a51a7f69db93a14b1ee6b1a7', 859 | hash: '4cc0329b2c0cb32e0451fa3179bd944d4cd0fcf410939172f979e9fd2aa9f5f3' } ] 860 | ``` 861 | 862 | 863 | ## Git, Git, Git - The Stupid Content Tracker with Crypto Hashes 864 | 865 | _Everything is local. Distributed is the new centralized._ 866 | 867 | ![](i/xkcd1597.png) 868 | 869 | 870 | ### Quotes - Blockchains and Git 871 | 872 | > Yep, that's the joke. Nobody has been able to explain to me how the "blockchain" buzzword is significantly different to "git repo". 873 | > -- [Yaakov](https://twitter.com/yaakov_h/status/902659507255312384) 874 | > 875 | > But if you said "let's build a currency where all transactions are stored in a git repo" 876 | > you wouldn't be taken seriously for even 24 hrs. 877 | > -- [Yaakov](https://twitter.com/yaakov_h/status/902659847224664064) 878 | 879 | > Soon explaining git like "a git repo is like a blockchain with commits instead of blocks". 880 | > -- [Nicolás Berger](https://twitter.com/nicoberger/status/901776907418697729) 881 | > 882 | > "A local branch is like a state channel. It can be pushed and merged into the master blockchain at any moment." 883 | > -- [Nicolás Berger](https://twitter.com/nicoberger/status/901777571456614400) 884 | 885 | > The #Blockchain has changed the world. Here I make the argument that the #Blockchain is just like #git. 886 | > -- [Jackson Kelley](https://twitter.com/sjkelleyjr/status/901464041163341824) 887 | 888 | > `git merge [-m REF] [-g BLOB] --push` 889 | > Merge and push all signed commits to the blockchain. 890 | > -- [Git Commands](https://twitter.com/git_commands/status/935574015015612416) 891 | 892 | 893 | ### Books 894 | 895 | [**Learn Enough Git to Be Dangerous**](https://learnenough.com/git-tutorial) by Michael Hartl - FREE (Online Version) -- 896 | _Getting started ++ 897 | Backing up and sharing ++ 898 | Intermediate workflow ++ 899 | Collaborating ++ 900 | Conclusion ++ 901 | Advanced setup_ 902 | 903 | 904 | [**Pro Git**](https://git-scm.com/book) by Scott Chacon and Ben Straub, 2nd Edition, 2014 - FREE (Online Version) -- 905 | _Getting Started ++ 906 | Git Basics ++ 907 | Git Branching ++ 908 | Git on the Server ++ 909 | Distributed Git ++ 910 | GitHub ++ 911 | Git Tools ++ 912 | Customizing Git ++ 913 | Git and Other Systems ++ 914 | Git Internals ++ 915 | A1: Git in Other Environments ++ 916 | A2: Embedding Git in your Applications ++ 917 | A3: Git Commands_ 918 | 919 | 920 | > Git gets easier once you get the basic idea that branches are homeomorphic endofunctors 921 | > mapping submanifolds of a Hilbert space. 922 | > -- Anonymous 923 | 924 | 925 | ### Open Distributed Databases on Git 926 | 927 | [**football.db**](https://github.com/openfootball) - open public domain football datasets (incl. clubs, national teams, leagues, match schedules, etc.) 928 | 929 | [**world.db**](https://github.com/openmundi) - open public domain world (country) datasets 930 | 931 | [**beer.db**](https://github.com/openbeer) - open public domain beer & brewery datasets 932 | 933 | > Add a beer transaction to the #blockchain on #git and win a free Wiener Lager beer! Cheers. Prost. 934 | > -- [Gerald Bauer @ Austria Codes](https://twitter.com/austriacodes/status/907240018435088384) 935 | 936 | 937 | 938 | ### Open Distributed (Hyper) Ledger Books on Git 939 | 940 | [**Shilling (or Schilling)**](https://github.com/bitshilling/bitshilling) - Shilling on the Blockchain! - Rock-Solid Alpine Dollar from Austria 941 | 942 | [**Tulips**](TULIPS.md) - Tulips on the Blockchain! - Learn by Example from the Real World (Anno 1637) - Buy! Sell! Hold! Enjoy the Beauty of Admiral of Admirals, Semper Augustus, and More 943 | 944 | 945 | 946 | ## Classic Tulip Mania 947 | 948 | _A period in the Dutch Golden Age during which contract prices for bulbs of the recently introduced tulip reached extraordinarily high levels and then dramatically collapsed in February 1637._ 949 | 950 | ![](i/tulipmania-ii.png) 951 | 952 | 953 | ### Quotes - Blockchains are the next Internets / Tulips 954 | 955 | > People who compare digital tokens to tulips are essentially saying digital tokens are a bubble backed 956 | > by nothing but pure hype and speculation. 957 | > 958 | > What they fail to understand is that tulips come from dirt, not a blockchain. 959 | > 960 | > And as we all know, blockchain is possibly the best technological innovation since the internet. 961 | > It will have a tremendous impact on global business and society in general. 962 | > -- [TulipToken](http://tuliptoken.com) 963 | 964 | 965 | ### Books 966 | 967 | **Tulipomania: The Story of the World's Most Coveted Flower & the Extraordinary Passions It Aroused** by Mike Dash, 2001 -- 968 | _A Mania for Tulips ++ 969 | The Valley of Tien Shan ++ 970 | Within the Abode of Bliss ++ 971 | Stranger from the East ++ 972 | Clusius ++ 973 | Leiden ++ 974 | An Adornment to the Cleavage ++ 975 | The Tulip in the Mirror ++ 976 | Florists ++ 977 | Boom ++ 978 | At the Sign of the Golden Grape ++ 979 | The Orphans of Wouter Winkel ++ 980 | Bust ++ 981 | Goddess of Whores ++ 982 | At the Court of the Tulip King ++ 983 | Late Flowering_ 984 | 985 | **Tulipmania: Money, Honor, and Knowledge in the Dutch Golden Age** by Anne Goldgar, 2007 -- 986 | _Something Strange ++ 987 | Art & Flowers ++ 988 | Bloemisten ++ 989 | Grieving Money ++ 990 | Bad Faith ++ 991 | Cabbage Fever ++ 992 | Glossary ++ 993 | A Note on Money_ 994 | 995 | ![](i/tulipmania.png) 996 | 997 | 998 | ## Breaking News: CryptoKitties (Yes, Cute Little Cartoon Cats) on the Blockchain! 999 | 1000 | Collectible. Breedable. Adorable. 1001 | 1002 | Collect and breed digital cats. Start meow. Buy! Sell! Hold! 1003 | 1004 | Learn more @ [cryptokitties.co](https://cryptokitties.co) 1005 | 1006 | 1007 | ![](i/cryptokitties-top10-sales.png) 1008 | 1009 | 1010 | 1013 | 1014 | Latest (and Greatest) Investment Opportunity! 1015 | 1016 | > Blockchain has unlocked the magic of digital scarcity, and combining that with the power of 1017 | > making the digital goods persistent gives them a potential value that is only limited by how much 1018 | > prestige a wealthy person might place on ownership of the item. 1019 | > 1020 | > -- [Justin Poirier](https://twitter.com/tokenizedcap/status/938460753589424128)‏ 1021 | 1022 | > All I want for Christmas is a CryptoKitty. 1023 | > 1024 | > -- [Kayla Williams](https://twitter.com/kaylaw/status/938590748655550464) 1025 | 1026 | > I got a fever. And the only prescription is more CryptoKitties. 1027 | > 1028 | > -- [Eduardo Salazar](https://twitter.com/ceduardosalazar/status/938558630663634944) 1029 | 1030 | > My Gen 7 CryptoKitty #104375. The Future is Meow. 1031 | > 1032 | > -- [Anshul Dhawan](https://twitter.com/TheAnshulDhawan/status/938551642202324993) 1033 | 1034 | 1035 | ![](i/cryptokitties-genes01.png) 1036 | 1037 | > - Fabulous Persian Spock Gerbil Gold Cottoncandy - Extremely rare gen 5 swift virgin | 2.9 ETH 1038 | > - Rarity: 0.00264% Gen 5 JAGUAR FABULOUS GOLD DALI!! VIRGIN! 1039 | > - Rarity: 0.0015% Princess Bubblegum is now for sale! Gen 12 | Brisk | Virgin | Chartreux | Bubblegum | Otaku | Emeraldgreen | Saycheese | Mauveover | Spock - Starts ETH 20/Ends ETH 10 1040 | > - Gold ducat, Gen 5, Virgin, Swift. Very cheap 1041 | > - Cheap Gen 1 cute kittie with rare genes! Only 0.125 ETH 1042 | > - UNIQUE Virgin Peach Googly Gold Mauveover gen:2 cooldown:1 0.87992% RARE 1043 | > - SUPER CHEAP: Gerbil, Ragdoll, Scarlet, Chestnut, Cotton Candy!!! 0.02 ETH (~$14) 1044 | > - I'm giving away a Gen 1 FAST Gold for free... 1045 | > 1046 | > -- [CrypoKittiesMarket](https://www.reddit.com/r/CryptoKittiesMarket) 1047 | 1048 | ### Awesome CryptoKitties (and CryptoCopycats) 1049 | 1050 | ![](i/cryptokitties-modernart-paintings.png) 1051 | 1052 | A collection about Awesome CryptoKitties (Yes, Cute Little Cartoon Cats) on the Blockchain! and CryptoCopycats - digital collectibles secured on a distributed public databases w/ crypto hashes. Are CryptoPuppies the new CryptoKitties? Learn by Example from the Real World (Anno 2017) - Buy! Sell! Hodl! 1053 | 1054 | More @ [cryptocopycats/awesome-cryptokitties](https://github.com/cryptocopycats/awesome-cryptokitties) 1055 | 1056 | ![](i/cryptokitties-modernart-paintings-iii.png) 1057 | 1058 | 1059 | 1060 | ## Events, Meetups, Orgs 1061 | 1062 | _Revolutionize the world one country at a time. Blockchainers of the world, unite!_ 1063 | 1064 | - [**Blockchain Austria • Blockkette Österreich**](https://github.com/austriacodes/blockchain-austria) -- distributed centralized page for blockchain meetups & orgs in Austria (Central Europe) 1065 | 1066 | 1067 | 1068 | ## Awesome Awesomeness 1069 | 1070 | _A curated list of awesome lists._ 1071 | 1072 | - [**Blockchain Stuff**](https://github.com/Xel/Blockchain-stuff) -- a curated list of blockchain and general cryptocurrency resources 1073 | - [**Blockchain Roadmap**](https://roadmap.sh/blockchain) -- a step-by-step roadmap / guide to become a blockchain programmer 1074 | - [**Awesome Blockchain**](https://github.com/igorbarinov/awesome-blockchain) by Igor Barinov et al -- a curated list of the bitcoin blockchain services 1075 | - [**Awesome Blockchain**](https://github.com/imbaniac/awesome-blockchain) by Tim Reznich et al -- a curated list of blockchain services and exchanges 1076 | - [**Awesome Blockchain**](https://github.com/istinspring/awesome-blockchain) by `istinspring` et al -- a curated list of awesome projects and services based on blockchain technology 1077 | - [**Awesome Coins**](https://github.com/kennethreitz/awesome-coins) by Kenneth Reitz et al -- a guide to crypto-currencies and their algos 1078 | - [**Awesome CryptoKitties (and CryptoCopycats)**](https://github.com/openblockchains/awesome-cryptokitties) by Gerald Bauer et al -- a curated list about the awesome crypto kitties and copycats 1079 | - [**Awesome Git**](https://github.com/dictcp/awesome-git) by Dick Tang et al -- a curated list of amazingly awesome Git tools, resources and shiny things 1080 | - [**Awesome**](https://github.com/sindresorhus/awesome) by Sindre Sorhus et al -- a curated list of awesome lists 1081 | 1082 | 1083 | 1084 | ## Meta 1085 | 1086 | **License** 1087 | 1088 | ![](https://publicdomainworks.github.io/buttons/zero88x31.png) 1089 | 1090 | The awesome list is dedicated to the public domain. Use it as you please with no restrictions whatsoever. 1091 | --------------------------------------------------------------------------------