├── .gitignore ├── README.md ├── blockchain.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blockgeeks: Build Your Own Blockchain with JavaScript 2 | Code that shows how to build your own Bitcoin-alike blockchain with JavaScript. 3 | 4 | I want to thank [Savjee](https://github.com/SavjeeTutorials) for making this article possible. -------------------------------------------------------------------------------- /blockchain.js: -------------------------------------------------------------------------------- 1 | const SHA256 = require("crypto-js/sha256"); 2 | 3 | class Transaction{ 4 | constructor(fromAddress, toAddress, amount){ 5 | this.fromAddress = fromAddress; 6 | this.toAddress = toAddress; 7 | this.amount = amount; 8 | } 9 | } 10 | 11 | class Block { 12 | constructor(timestamp, transactions, previousHash = '') { 13 | this.previousHash = previousHash; 14 | this.timestamp = timestamp; 15 | this.transactions = transactions; 16 | this.hash = this.calculateHash(); 17 | this.nonce = 0; 18 | } 19 | 20 | calculateHash() { 21 | return SHA256(this.previousHash + this.timestamp + JSON.stringify(this.transactions) + this.nonce).toString(); 22 | } 23 | 24 | mineBlock(difficulty) { 25 | while (this.hash.substring(0, difficulty) !== Array(difficulty + 1).join("0")) { 26 | this.nonce++; 27 | this.hash = this.calculateHash(); 28 | } 29 | 30 | console.log("BLOCK MINED: " + this.hash); 31 | } 32 | } 33 | 34 | 35 | class Blockchain{ 36 | constructor() { 37 | this.chain = [this.createGenesisBlock()]; 38 | this.difficulty = 4; 39 | this.pendingTransactions = []; 40 | this.miningReward = 100; 41 | } 42 | 43 | createGenesisBlock() { 44 | return new Block(Date.parse("2017-01-01"), [], "0"); 45 | } 46 | 47 | getLatestBlock() { 48 | return this.chain[this.chain.length - 1]; 49 | } 50 | 51 | minePendingTransactions(miningRewardAddress){ 52 | let block = new Block(Date.now(), this.pendingTransactions, this.getLatestBlock().hash); 53 | block.mineBlock(this.difficulty); 54 | 55 | console.log('Block successfully mined!'); 56 | this.chain.push(block); 57 | 58 | this.pendingTransactions = [ 59 | new Transaction(null, miningRewardAddress, this.miningReward) 60 | ]; 61 | } 62 | 63 | createTransaction(transaction){ 64 | this.pendingTransactions.push(transaction); 65 | } 66 | 67 | getBalanceOfAddress(address){ 68 | let balance = 0; 69 | 70 | for(const block of this.chain){ 71 | for(const trans of block.transactions){ 72 | if(trans.fromAddress === address){ 73 | balance -= trans.amount; 74 | } 75 | 76 | if(trans.toAddress === address){ 77 | balance += trans.amount; 78 | } 79 | } 80 | } 81 | 82 | return balance; 83 | } 84 | 85 | isChainValid() { 86 | for (let i = 1; i < this.chain.length; i++){ 87 | const currentBlock = this.chain[i]; 88 | const previousBlock = this.chain[i - 1]; 89 | 90 | if (currentBlock.hash !== currentBlock.calculateHash()) { 91 | return false; 92 | } 93 | 94 | if (currentBlock.previousHash !== previousBlock.hash) { 95 | return false; 96 | } 97 | } 98 | 99 | return true; 100 | } 101 | } 102 | 103 | let codeCoin = new Blockchain(); 104 | codeCoin.createTransaction(new Transaction('address1', 'address2', 100)); 105 | codeCoin.createTransaction(new Transaction('address2', 'address1', 50)); 106 | 107 | console.log('\n Starting the miner...'); 108 | codeCoin.minePendingTransactions('michiel-address'); 109 | 110 | console.log('\nBalance of Michiel is', codeCoin.getBalanceOfAddress('michiel-address')); 111 | 112 | console.log('\n Starting the miner again...'); 113 | codeCoin.minePendingTransactions('michiel-address'); 114 | 115 | console.log('\nBalance of Michiel is', codeCoin.getBalanceOfAddress('michiel-address')); 116 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "build-your-own-blockchain", 3 | "main": "blockchain.js", 4 | "scripts": { 5 | "start": "node blockchain.js" 6 | }, 7 | "dependencies": { 8 | "crypto-js": "^3.1.9-1" 9 | } 10 | } --------------------------------------------------------------------------------