JavaScript implements blockchain and javascript Blocks

Source: Internet
Author: User

JavaScript implements blockchain and javascript Blocks

Almost everyone has heard of cryptocurrencies like Bitcoin and Bitcoin, but only a few people know the technology behind them. In this article, I will use JavaScript to create a simple blockchain to demonstrate how they work internally. I will call it SavjeeCoin!

The full text is divided into three parts:

  1. Part1: implement a basic blockchain
  2. Part2: Implement POW
  3. Part3: Trading and mining rewards

Part1: implement a basic blockchain

Blockchain

Blockchain is a public database composed of blocks that can be accessed by anyone. This seems nothing special, but they have an interesting property: they are immutable. Once a block is added to the blockchain, it will not be changed unless the remaining blocks are invalidated.

This is why the encrypted currency is based on blockchain. You certainly don't want people to change the transaction after the transaction is completed!

Create a block

Blockchain is linked together by many blocks (it sounds like there is no problem ..). Blockchain blocks allow us to detect whether any previous block has been manipulated in some way.

So how can we ensure data integrity? Each block contains a hash calculated based on its content. It also contains the hash of the previous block.

Below is a block class written in JavaScript:

const SHA256 = require("crypto-js/sha256");class Block { constructor(index, timestamp, data, previousHash = '') { this.index = index; this.previousHash = previousHash; this.timestamp = timestamp; this.data = data; this.hash = this.calculateHash(); } calculateHash() { return SHA256(this.index + this.previousHash + this.timestamp + JSON.stringify(this.data)).toString(); }}

Because JavaScript does not support sha256, I introduced the crypto-js library. Then I defined a constructor to initialize the attributes of my blocks. The index attribute is assigned to each block to indicate the location of the block on the entire chain. We also generate a timestamp and some data that needs to be stored in the block. The last part is the hash of the previous block.

Create a chain

Now we can link the block in the Blockchain class! The following code is implemented using JavaScript:

class Blockchain{ constructor() { this.chain = [this.createGenesisBlock()]; } createGenesisBlock() { return new Block(0, "01/01/2017", "Genesis block", "0"); } getLatestBlock() { return this.chain[this.chain.length - 1]; } addBlock(newBlock) { newBlock.previousHash = this.getLatestBlock().hash; newBlock.hash = newBlock.calculateHash(); this.chain.push(newBlock); } isChainValid() { for (let i = 1; i < this.chain.length; i++){  const currentBlock = this.chain[i];  const previousBlock = this.chain[i - 1];  if (currentBlock.hash !== currentBlock.calculateHash()) {  return false;  }  if (currentBlock.previousHash !== previousBlock.hash) {  return false;  } } return true; }}

In the constructor, I create an array containing the creation block to initialize the entire chain. The first block is special because it cannot refer to the forward block. I have added the following two methods:

  • GetLatestBlock () returns the latest block on our blockchain.
  • AddBlock () is responsible for adding new blocks to our chain. To this end, we add the hash of the previous block to our new block. In this way, we can maintain the integrity of the entire chain. As long as we change the content of the latest block, we need to recalculate its hash. After the calculation is complete, I will push the block into the chain (an array ).

Finally, I createisChainValid() To ensure that no one has tampered with the blockchain. It traverses all blocks to check whether the hash of each block is correct. It comparespreviousHash To check whether each block points to the correct previous block. If everything is okay, it returns true or false.

Use blockchain

Our blockchain class has been written and can be used now!

let savjeeCoin = new Blockchain();savjeeCoin.addBlock(new Block(1, "20/07/2017", { amount: 4 }));savjeeCoin.addBlock(new Block(2, "20/07/2017", { amount: 8 }));

Here I just created a blockchain instance and named it SavjeeCoin! Then I added some blocks to the chain. The block can contain any data you want, but in the code above, I chose to add an object with the amount attribute.

Try it!

In the introduction, I once said that blockchain is immutable. Once added, the block cannot be changed. Let's have a try!

// Check whether it is valid (true will be returned) console. log ('blockchain valid? '+ SavjeeCoin. isChainValid (); // try to change the data savjeeCoin. chain [1]. data = {amount: 100}; // check whether it is valid again (false will be returned) console. log ("Blockchain valid? "+ SavjeeCoin. isChainValid ());

At the beginning, I will run isChainValid () to verify the integrity of the entire chain. We have operated on any block, so it returns true.

Then I changed the data in the first blockchain (Index 1) block. Then I checked the integrity of the entire chain again and found that it returned false. Our entire chain is no longer valid.

Conclusion

This small chestnut is far from complete. It has not yet implemented POW (workload proof mechanism) or P2P networks to communicate with other miners.

But he does prove how blockchain works. Many people think that the principles will be very complex, but this article proves that the basic concepts of blockchain are very easy to understand and implement.

Part2: Implement POW (proof-of-work: proof of workload)

In part1, we used JavaScript to create a simple blockchain to demonstrate how blockchain works. However, this implementation is incomplete, and many people find that the system can still be tampered. That's right! Our blockchain needs another mechanism to defend against attacks. Let's take a look at how we can achieve this!

Problem

Now we can quickly create blocks and quickly add them to our blockchain. However, this leads to three problems:

  • First, people can quickly create blocks and fill our chains with garbage. A large number of blocks will overload our blockchain and make it unusable.
  • Second, because it is too easy to create a valid block, people can tamper with a block in the chain and re-calculate the hash of all blocks. Even if they have tampered with blocks, they can still end with valid blocks.
  • Third, you can effectively control the blockchain by combining the above two flaws. The blockchain is driven by a p2p network, where the node adds the blockchain to the available longest chain. Therefore, you can tamper with the block, compute all other blocks, and add any more blocks you want to add. In the end, you will get the longest chain, and all other nodes will accept it and add their own blocks to it.

Obviously, we need a solution to solve these problems: POW.

What is POW?

POW is a mechanism that existed before the first blockchain was created. This is a simple technology that prevents abuse through a certain amount of computing. Workload is the key to preventing spam filling and tampering. If it requires a lot of computing power, it is no longer worthwhile to fill the garbage.

Bitcoin requires hash to implement POW with a specific number of zeros. This is also called difficulty.

But wait! How can the hash of a block be changed? In the bitcoin scenario, a block contains various financial transaction information. We certainly do not want to confuse the data to get the correct hash.

To solve this problem, a nonce value is added to the blockchain. Nonce is the number of times a valid Hash is queried. Furthermore, the output of the hash function cannot be predicted. Therefore, before obtaining a hash that meets the difficulty conditions, you can only try a large number of combinations. Finding a valid hash (creating a new block) is called mining in the circle.

In bitcoin scenarios, POW ensures that only one block can be added every 10 minutes. You can imagine how much computing power the spammers need to create a new block. It is difficult for them to cheat the network, let alone tamper with the entire chain.

Implement POW

How can we implement it? First, modify the block class and add the Nonce variable to its constructor. I will initialize it and set its value to 0.

constructor(index, timestamp, data, previousHash = '') { this.index = index; this.previousHash = previousHash; this.timestamp = timestamp; this.data = data; this.hash = this.calculateHash(); this.nonce = 0;}

We also need a new method to add Nonce until we get a valid hash. It is determined by the difficulty. Therefore, we will receive the difficulty as a parameter.

mineBlock(difficulty) { while (this.hash.substring(0, difficulty) !== Array(difficulty + 1).join("0")) {  this.nonce++;  this.hash = this.calculateHash(); } console.log("BLOCK MINED: " + this.hash);}

Finally, we need to change it.calculateHash() Function. This is because he has not used Nonce to calculate the hash.

calculateHash() { return SHA256(this.index + this.previousHash + this.timestamp + JSON.stringify(this.data) + this.nonce ).toString();}

When you combine them, you will get the following block classes:

class Block { constructor(index, timestamp, data, previousHash = '') { this.index = index; this.previousHash = previousHash; this.timestamp = timestamp; this.data = data; this.hash = this.calculateHash(); this.nonce = 0; } calculateHash() { return SHA256(this.index + this.previousHash + this.timestamp + JSON.stringify(this.data) + this.nonce).toString(); } mineBlock(difficulty) { while (this.hash.substring(0, difficulty) !== Array(difficulty + 1).join("0")) {  this.nonce++;  this.hash = this.calculateHash(); } console.log("BLOCK MINED: " + this.hash); }}

Modify blockchain

Now that our block already has Nonce and can be mined, we also need to ensure that our blockchain supports this new behavior. Let's add a new attribute to the blockchain to track the difficulty of the entire chain. I will set it to 2 (this means that the hash of the block must start with 2 zeros ).

constructor() { this.chain = [this.createGenesisBlock()]; this.difficulty = 2;}

Now all you have to do is change the addBlock () method so that you can make sure that the block is actually dug before you add it to the chain. Next we will pass the difficulty to the block.

addBlock(newBlock) { newBlock.previousHash = this.getLatestBlock().hash; newBlock.mineBlock(this.difficulty); this.chain.push(newBlock);}


Success! Our blockchain now has a POW to defend against attacks.

Test

Now let's test our blockchain to see what the effect of adding a new block under POW. I will use the previous code. We will create a new blockchain instance and add two blocks to it.

let savjeeCoin = new Blockchain();console.log('Mining block 1');savjeeCoin.addBlock(new Block(1, "20/07/2017", { amount: 4 }));console.log('Mining block 2');savjeeCoin.addBlock(new Block(2, "20/07/2017", { amount: 8 }));

If you run the above Code, you will find that adding new blocks is still very fast. This is because the current difficulty is only 2 (or your computer performance is very good ).

If you create a 5-level blockchain instance, you will find that your computer will spend about 10 seconds mining. As the difficulty increases, your defense against attacks will be more protected.

Disclaimer

As mentioned earlier: this is by no means a complete blockchain. It still lacks many features (such as P2P networks ). This is just to illustrate how blockchain works.

Moreover, it is not fast to use JavaScript for mining because of a single thread.

Part3: Trading and mining rewards

In the previous two parts, we created a simple blockchain and added POW to defend against attacks. However, we are also lazy on the road: Our blockchain can only store a transaction in one block, and there is no reward for miners. Now, let's solve this problem!

Refactoring block class

Currently, a block has index, previushash, timestamp, data, hash, and nonce attributes. This index attribute is not very useful. In fact, I don't even know why I want to add it. So I removed it and renamed data transactions to make it more semantic.

class Block{ constructor(timestamp, transactions, previousHash = '') { this.previousHash = previousHash; this.timestamp = timestamp; this.transactions = transactions; this.hash = this.calculateHash(); this.nonce = 0; }}

When we change the block class, we must also change the calculateHash () function. It is still using the old index and data attributes.

calculateHash() { return SHA256(this.previousHash + this.timestamp + JSON.stringify(this.transactions) + this.nonce).toString();}

Transaction type

In the block, we can store multiple transactions. Therefore, we also need to define a transaction class, while we can lock the attributes that a transaction should have:

class Transaction{ constructor(fromAddress, toAddress, amount){ this.fromAddress = fromAddress; this.toAddress = toAddress; this.amount = amount; }}

This transaction example is very simple. It only contains fromAddress, toAddress, and quantity. If necessary, you can add more fields to it, but this is only for minimum implementation.

Adjust Our blockchain

Current biggest task: Adjust Our blockchain to adapt to these new changes. The first thing we need to do is store the transaction to be processed.

As you know, because of POW, blockchain can stably create blocks. In the bitcoin scenario, it is difficult to create a new block every 10 minutes. However, you can submit new transactions between two blocks.

To do this, we need to first change the blockchain constructor so that it can store transactions to be processed. We will also create a new property to define how much the Miner gets as a reward:

Class Blockchain {constructor () {this. chain = [this. createGenesisBlock ()]; this. difficulty = 5; // The place where transactions are stored between blocks. this. pendingTransactions = []; // mining return this. miningReward = 100 ;}}

Next, we will adjust our addBlock () method. However, my adjustment refers to deleting and rewriting it! We will no longer allow people to directly add blocks to the chain. Instead, they must add the transaction to the next block. In addition, we rename addBlock () to createTransaction (), which looks more semantic:

CreateTransaction (transaction) {// here there should be some validation! // Push the array of transactions to be processed this. pendingTransactions. push (transaction );}

Mining

Now, you can add new transactions to the list of pending transactions. But in any case, we need to clear them and move them into the actual block. To this end, we create minePendingTransactions() Method. This method not only mines all new blocks to be traded, but also sends incentives to miners.

MinePendingTransactions (miningRewardAddress) {// use all transactions to create and excavate new blocks .. let block = new Block (Date. now (), this. pendingTransactions); block. mineBlock (this. difficulty); // Add the newly dug ore to the chain. this. chain. push (block); // reset the list of pending transactions and send rewards this. pendingTransactions = [new Transaction (null, miningRewardAddress, this. miningReward)];}

Note that this method uses the miningRewardAddress parameter. If you start mining, you can pass your wallet address to this method. Once the mining is successful, the system will create a new transaction to reward you for mining (100 coins in this chestnut ).

Note that in this example, we add all pending transactions to a block. But in fact, the block size is limited, so this is not feasible. In bitcoin, the size of a block is about 2 Mb. If more transactions can be squeezed into a block, miners can choose which transactions are concluded and which ones are not concluded (usually more expensive transactions are easy to win ).

Address balance

Let's do one more thing after testing our code! It would be better to check the balance of the address on our blockchain.

GetBalanceOfAddress (address) {let balance = 0; // you start at zero! // Traverse each block and the transactions in each block for (const block of this. chain) {for (const trans of block. transactions) {// if the address is the initiator-> reduce the balance if (trans. fromAddress === address) {balance-= trans. amount;} // if the address is a receiver-> increase the balance if (trans. toAddress = address) {balance + = trans. amount; }}return balance ;}

Test

Okay, we have completed and can final all work properly! To this end, we have created some transactions:

let savjeeCoin = new Blockchain();console.log('Creating some transactions...');savjeeCoin.createTransaction(new Transaction('address1', 'address2', 100));savjeeCoin.createTransaction(new Transaction('address2', 'address1', 50));

These transactions are currently in the waiting status. To make them confirmed, we must start mining:

console.log('Starting the miner...');savjeeCoin.minePendingTransactions('xaviers-address');

When we start mining, we will also deliver an address that we want to receive mining rewards. In this case, my address is xaviers-address (very complicated !).

Then, let's check the account balance of xaviers-address:

Console. log ('balance of Xaviers address is ', savjeeCoin. getBalanceOfAddress ('xaviers-address'); // output: 0

My account output is 0 ?! Wait, why? Shouldn't I be rewarded with mine mining? Then, if you carefully observe the code, you will see that the system will create a transaction, and then add your mining reward to the new pending transaction. The transaction will be included in the next block. So if we start mining again, we will receive our 100 coins!

Console. log ('starting the miner again! '); SavjeeCoin. minePendingTransactions ("xaviers-address"); console. log ('balance of Xaviers address is ', savjeeCoin. getBalanceOfAddress ('xaviers-address'); // output: 100

Limitations and conclusions

Now, our blockchain can store multiple transactions on one block, and it can bring a return to miners.

However, there are still some shortcomings: the sending currency is, we do not check whether the initiator has enough balance to actually trade. However, this is actually an easy solution. We have not created a new wallet or signature transaction (traditionally encrypted with a public/private key ).

Disclaimer & source code

I would like to point out that this is by no means a complete blockchain implementation! It still lacks many features. This is just to verify some concepts to help you understand how blockchain works.

The source code of this project is stored in my GitHub.

Summary

The above section describes how to implement blockchain using JavaScript. I hope it will help you. If you have any questions, please leave a message and I will reply to you in a timely manner. Thank you very much for your support for the help House website!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.