This is a simplified POW Blockchain network. POW (or proof of work) is a method of validating blockchain transactions that relies on physical miners to solve hash based algorithms. POW is a network architecture that is used in many different Blockchain projects, however this specific arcitecture is most similar to the Bitcoin network
Created
October 31, 2022 08:35
-
-
Save zoxee/fc7465e8197538aa14493d40da2716ea to your computer and use it in GitHub Desktop.
Simple Proof Of Work Blockchain
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="container"> | |
<h1>Simple Proof Of Work Blockchain</h1> | |
<div class="text"> | |
<p><span class="number">01</span> <span class="green">class </span><span class="orange">Blockchain </span>{</p> | |
<p><span class="number">02</span> | |
<span class="indent"></span> | |
<span class="red">constructor</span>(difficulty) {</p> | |
<p><span class="number">03</span><span class="indent"></span><span class="indent"></span> this.<span class="blue">difficulty =</span> difficulty;</p> | |
<p><span class="number">04</span><span class="indent"></span><span class="indent"></span> this.<span class="blue">blocks =</span> [];</p> | |
<p><span class="number">05</span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="number">// Add Genesis Block</span></p> | |
<p><span class="number">06</span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="red">var </span>genesisBlock <span class="blue">= </span><span class="red">new </span><span class="orange">Block</span>(<span class="blue">0</span>, <span class="blue">null</span>, <span class="orange">Date</span>.<span class="red">now</span>(), "Genesis block");</p> | |
<p><span class="number">07</span><span class="indent"></span><span class="indent"></span> genesisBlock.<span class="red">mineBlock</span>(this.<span class="blue">difficulty</span>);</p> | |
<p><span class="number">08</span><span class="indent"></span><span class="indent"></span> this.<span class="blue">blocks</span>.<span class="red">push</span>(genesisBlock);</p> | |
<p><span class="number">09</span><span class="indent"></span> }</p> | |
<p><span class="number">10</span> }</p> | |
<p><span class="number">11</span></p> | |
<p><span class="number">12</span><span class="orange"> Blockchain</span>.<span class="blue">prototype</span>.<span class="red">newBlock</span><span class="blue"> =</span><span class="darkGreen"> function</span>(data) {</p> | |
<p><span class="number">13</span><span class="indent"></span><span class="red"> var</span> latestBlock<span class="blue"> =</span> this.<span class="blue">blocks</span>[this.<span class="blue">blocks</span>.<span class="blue">length - 1</span>];</p> | |
<p><span class="number">14</span><span class="indent"></span><span class="red"> return new </span><span class="orange">Block</span>(latestBlock.<span class="blue">index + 1</span>, latestBlock.<span class="blue">hash</span>,<span class="orange"> Date</span>.<span class="red">now</span>(), data);</p> | |
<p><span class="number">15</span> }</p> | |
<p><span class="number">16</span><span class="orange"> Blockchain</span>.<span class="blue">prototype</span>.<span class="red">addBlock</span><span class="blue"> =</span><span class="darkGreen"> function</span>(block) {</p> | |
<p><span class="number">17</span><span class="indent"></span> block.<span class="red">mineBlock</span>(this.<span class="blue">difficulty</span>);</p> | |
<p><span class="number">18</span><span class="indent"></span> this.<span class="blue">blocks</span>.<span class="red">push</span>(block);</p> | |
<p><span class="number">19</span> }</p> | |
<p><span class="number">20</span></p> | |
<p><span class="number">21</span><span class="orange"> Blockchain</span>.<span class="blue">prototype</span>.<span class="red">isFirstBlockValid</span><span class="blue"> =</span><span class="darkGreen"> function</span>() {</p> | |
<p><span class="number">22</span><span class="indent"></span><span class="red"> var</span> firstBlock<span class="blue"> =</span> this.<span class="blue">blocks</span>[<span class="blue">0</span>];</p> | |
<p><span class="number">23</span><span class="indent"></span><span class="red"> if</span> (firstBlock.<span class="blue">index</span> != <span class="blue">0</span>) {</p> | |
<p><span class="number">24</span><span class="indent"></span><span class="indent"></span><span class="red"> return</span><span class="blue"> false</span>;</p> | |
<p><span class="number">25</span><span class="indent"></span> }</p> | |
<p><span class="number">26</span><span class="indent"></span><span class="red"> if</span> (firstBlock.<span class="blue">previousHash</span> == <span class="blue">null</span>) {</p> | |
<p><span class="number">27</span><span class="indent"></span><span class="indent"></span><span class="red"> return</span><span class="blue"> false</span>;</p> | |
<p><span class="number">28</span><span class="indent"></span> }</p> | |
<p><span class="number">29</span><span class="indent"></span><span class="red"> if</span> (firstBlock.<span class="blue">hash == null ||</span><span class="red"> calculateHash</span>(firstBlock) != firstBlock.<span class="blue">hash</span>) {</p> | |
<p><span class="number">30</span><span class="indent"></span><span class="indent"></span><span class="red"> return</span><span class="blue"> false</span>;</p> | |
<p><span class="number">31</span><span class="indent"></span> }</p> | |
<p><span class="number">32</span></span><span class="indent"></span><span class="red"> return</span><span class="blue"> true</span>;</p> | |
</p> | |
<p><span class="number">33</span> }</p> | |
<p><span class="number">34</span></p> | |
<p><span class="number">35</span><span class="orange"> Blockchain</span>.<span class="blue">prototype</span>.<span class="red">isValidBlock</span><span class="blue"> =</span><span class="darkGreen"> function</span>(block, previousBlock) {</p> | |
<p><span class="number">36</span><span class="indent"></span><span class="red"> if</span> (previousBlock.<span class="blue">index + 1</span> != block.<span class="blue">index</span>) {</p> | |
<p><span class="number">37</span><span class="indent"></span><span class="indent"></span><span class="red"> return</span><span class="blue"> false</span>;</p> | |
<p><span class="number">38</span><span class="indent"></span> }</p> | |
<p><span class="number">39</span><span class="indent"></span><span class="red"> if</span> (block.<span class="blue">previousHash == null || </span>block.<span class="blue">previousHash</span> != previousBlock.<span class="blue">hash</span>) {</p> | |
<p><span class="number">40</span><span class="indent"></span><span class="indent"></span><span class="red"> return</span><span class="blue"> false</span>; | |
</p> | |
<p><span class="number">41</span><span class="indent"></span> }</p> | |
<p><span class="number">42</span><span class="indent"></span><span class="red"> if</span> (block.<span class="blue">hash == null || </span><span class="red">calculateHash</span>(block) != block.<span class="blue">hash</span>) {</p> | |
<p><span class="number">43</span><span class="indent"></span><span class="indent"></span><span class="red"> return</span><span class="blue"> false</span>;</p> | |
<p><span class="number">44</span><span class="indent"></span> }</p> | |
<p><span class="number">45</span><span class="indent"></span><span class="indent"></span><span class="red"> return</span><span class="blue"> true</span>;</p> | |
<p><span class="number">46</span> }</p> | |
<p><span class="number">47</span></p> | |
<p><span class="number">48</span><span class="orange"> Blockchain</span>.<span class="blue">prototype</span>.<span class="red">isBlockchainValid</span><span class="blue"> =</span><span class="darkGreen"> function</span>() {</p> | |
<p><span class="number">49</span><span class="indent"></span><span class="red"> if</span> (!this.<span class="red">isFirstBlockValid</span>()) {</p> | |
<p><span class="number">50</span><span class="indent"></span><span class="indent"></span><span class="red"> return</span><span class="blue"> false</span>;</p> | |
<p><span class="number">51</span><span class="indent"></span> }</p> | |
<p><span class="number">52</span><span class="indent"></span><span class="red"> for</span>(<span class="red">var</span> i<span class="blue"> = 1</span>; i<span class="blue"> | |
< </span>this.<span class="blue">blocks</span>.<span class="blue">length</span>; i<span class="blue">++</span>) {</p> | |
<p><span class="number">53</span><span class="indent"></span><span class="indent"></span><span class="red"> var</span> block<span class="blue"> =</span> this.<span class="blue">blocks</span>[i];</p> | |
<p><span class="number">54</span><span class="indent"></span><span class="indent"></span><span class="red"> var</span> previousBlock<span class="blue"> =</span> this.<span class="blue">blocks</span>[i<span class="blue"> - 1</span>];</p> | |
<p><span class="number">55</span><span class="indent"></span><span class="indent"></span><span class="red"> if</span> (!this.<span class="red">isValidBlock</span>(block, previousBlock)) {</p> | |
<p><span class="number">56</span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="red"> return</span><span class="blue"> false</span>;</p> | |
<p><span class="number">57</span><span class="indent"></span> }}</p> | |
<p><span class="number">58</span><span class="indent"></span><span class="red"> return</span><span class="blue"> true</span>;</p> | |
<p><span class="number">59</span> }</p> | |
<p><span class="number">60</span></p> | |
<p><span class="number">61</span><span class="orange"> Blockchain</span>.<span class="blue">prototype</span>.<span class="red">display</span><span class="blue"> =</span><span class="darkGreen"> function</span>() {</p> | |
<p><span class="number">62</span><span class="indent"></span><span class="red"> for </span>(<span class="red">var </span>i<span class="blue"> = 0</span>; i<span class="blue"> | |
< </span>this.<span class="blue">blocks</span>.<span class="blue">length</span>; i<span class="blue">++</span>) {</p> | |
<p><span class="number">63</span><span class="indent"></span><span class="indent"></span><span class="red"> var </span>block<span class="blue"> =</span> this.<span class="blue">blocks</span>[i];</p> | |
<p><span class="number">64</span><span class="indent"></span><span class="indent"></span><span class="red"> var </span>str<span class="blue"> = </span>"Block #"<span class="blue"> + </span>block.<span class="blue">index + </span>" ["<span class="blue"> +</span></p> | |
<p><span class="number">65</span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span> "previousHash: "<span class="blue"> + </span>block.<span class="blue">timestamp + </span>block.<span class="blue">timestamp + </span>", "<span class="blue"> +</span></p> | |
<p><span class="number">66</span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span> "timestamp: "<span class="blue"> + </span>block.<span class="blue">timestamp + </span>", "<span class="blue"> + </span></p> | |
<p><span class="number">67</span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span> "data: "<span class="blue"> + </span>block.<span class="blue">data + </span>", "<span class="blue"> + </span></p> | |
<p><span class="number">68</span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span><span class="indent"></span> "hash: "<span class="blue"> + </span>block.<span class="blue">hash + </span>"]";</p> | |
<p><span class="number">69</span><span class="indent"></span><span class="indent"></span> console.<span class="red">log</span>(str);</p> | |
<p><span class="number">70</span><span class="indent"></span> }</p> | |
<p><span class="number">71</span> }</p> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//We started by importing SHA-256 from cloudfare https://cdnjs.cloudflare.com/ajax/libs/js-sha256/0.9.0/sha256.min.js | |
// First we create our Block. The Block is what stores information on the blockchain. This includes the information we define in the Block structure. | |
class Block { | |
constructor(index, previousHash, timestamp, data) { | |
this.index = index; | |
this.previousHash = previousHash; | |
this.timestamp = timestamp; | |
this.data = data; | |
this.nonce = 0; | |
this.hash = calculateHash(this); | |
} | |
} | |
// Here we will create the Block and Blockchain hash. The has is what ensures the validity of the network. | |
function calculateHash(block) { | |
return sha256( | |
block.index + | |
block.previousHash + | |
block.timestamp + | |
block.data + | |
block.nonce | |
); | |
} | |
// Here we determine how Blocks are mined on the Blockchain. | |
Block.prototype.mineBlock = function (difficulty) { | |
this.nonce = 0; | |
var zeros = "0".repeat(difficulty); | |
while (this.hash.substring(0, difficulty) != zeros) { | |
this.nonce++; | |
this.hash = calculateHash(this); | |
} | |
}; | |
// This is where our Blockchain comes to life. This is the network architecture of our blockchain network. This allows us to determine how blocks are added to the network, how the mining difficulty is adjusted, check the validity of old blocks, new blocks, and verify the integrity of the network. | |
class Blockchain { | |
constructor(difficulty) { | |
this.difficulty = difficulty; | |
this.blocks = []; | |
// Add Genesis Block | |
var genesisBlock = new Block(0, null, Date.now(), "Genesis block"); | |
genesisBlock.mineBlock(this.difficulty); | |
this.blocks.push(genesisBlock); | |
} | |
} | |
Blockchain.prototype.newBlock = function (data) { | |
var latestBlock = this.blocks[this.blocks.length - 1]; | |
return new Block(latestBlock.index + 1, latestBlock.hash, Date.now(), data); | |
}; | |
Blockchain.prototype.addBlock = function (block) { | |
block.mineBlock(this.difficulty); | |
this.blocks.push(block); | |
}; | |
Blockchain.prototype.isFirstBlockValid = function () { | |
var firstBlock = this.blocks[0]; | |
if (firstBlock.index != 0) return false; | |
if (firstBlock.previousHash != null) return false; | |
if (firstBlock.hash == null || calculateHash(firstBlock) != firstBlock.hash) | |
return false; | |
return true; | |
}; | |
Blockchain.prototype.isValidBlock = function (block, previousBlock) { | |
if (previousBlock.index + 1 != block.index) return false; | |
if (block.previousHash == null || block.previousHash != previousBlock.hash) | |
return false; | |
if (block.hash == null || calculateHash(block) != block.hash) return false; | |
return true; | |
}; | |
Blockchain.prototype.isBlockchainValid = function () { | |
if (!this.isFirstBlockValid()) return false; | |
for (var i = 1; i < this.blocks.length; i++) { | |
var block = this.blocks[i]; | |
var previousBlock = this.blocks[i - 1]; | |
if (!this.isValidBlock(block, previousBlock)) return false; | |
} | |
return true; | |
}; | |
Blockchain.prototype.display = function () { | |
for (var i = 0; i < this.blocks.length; i++) { | |
var block = this.blocks[i]; | |
var str = | |
"Block #" + | |
block.index + | |
" [" + | |
"previousHash: " + | |
block.previousHash + | |
", " + | |
"timestamp: " + | |
block.timestamp + | |
", " + | |
"data: " + | |
block.data + | |
", " + | |
"hash: " + | |
block.hash + | |
"]"; | |
console.log(str); | |
} | |
}; | |
//Testing Blockchian Validity | |
// Open Console to see result | |
var blockchain = new Blockchain(4); | |
var block1 = blockchain.newBlock("Second Block"); | |
blockchain.addBlock(block1); | |
var block2 = blockchain.newBlock("Third Block"); | |
blockchain.addBlock(block2); | |
var block3 = blockchain.newBlock("Fourth Block"); | |
blockchain.addBlock(block3); | |
console.log("Blockchain Validity: " + blockchain.isBlockchainValid()); | |
blockchain.display(); | |
var block4 = new Block(12, "fakeHash", Date.now(), "Block Invalid"); | |
blockchain.addBlock(block4); | |
console.log("Blockchain Validity: " + blockchain.isBlockchainValid()); | |
blockchain.display(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-sha256/0.9.0/sha256.min.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* { | |
background: rgb(20, 18, 28); | |
font-family: "Source Code Pro", monospace; | |
} | |
.container { | |
display: flex; | |
flex-direction: column; | |
justify-content: flex-start; | |
align-items: center; | |
} | |
h1 { | |
color: white; | |
padding: 3%; | |
} | |
.text { | |
width: 80%; | |
} | |
p { | |
color: white; | |
} | |
.green { | |
color: #24c452; | |
} | |
.orange { | |
color: #ff9900; | |
} | |
.number { | |
color: #908796; | |
} | |
.red { | |
color: #e3244c; | |
} | |
.blue { | |
color: #0080d6; | |
} | |
.indent { | |
padding: 5px; | |
} | |
.darkGreen { | |
color: #1d7e5a; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment