Part 6: Implementing Blockchain and Cryptocurrency with PoW consensus algorithm
By: Kashish Khullar
Tags: Nodejs, Bitcoin, Tutorial, Cryptocurrency, Blockchain

A small scale, easy to understand yet, comprehensive, step by step implementation of Blockchain and cryptocurrency with Proof of Work consensus algorithm in node.js

Till now we have created our blockchain and p2p server, this completes the blockchain. In this part, we’ll create transactions.

Next, we’ll make a cryptocurrency over the blockchain we have just created. Remember, the data field in the blocks? That’s, where the transactions go.

To create a cryptocurrency we need a wallet. Wallet will have two keys, namely public and a corresponding private key. Public/private key pairs are a part of asymmetric cryptography which we will use to create digital signatures.

Digital signatures allow users to verify the miner which created the block and the transaction. Once a data is signed/encrypted using the private key it can only be verified/decrypted using the public key.

Note: the public key is known to the network and the private is kept private to the miner.

Before we move on let's understand how transactions work in the blockchain.

Transactions are a collection of scripts that indicate which person is sending how much to money to whom.

In blockchain, transactions have primarily two scripts, input scripts, and output scripts.

Input scripts include the timestamp, sender’s balance and the public key of the sender.

Output scripts include the amount we want to send to the sender and the public key of the sender

A basic transaction

In this figure we have a transaction on the left, the sender 0xfoo1 has a balance 500 and sends 40 to 0xbar2. But there is also another output script which is addressed to the sender itself. Note the sum of the amounts in the output scripts is equal to the balance mentioned in the input script. What really is happening here is that the sender sends all his currency into a transaction, a part of the transaction which is the first output script goes to the receiver, and the second comes back to the sender. Initially, he might send his entire balance, but later he receives his currency with the difference equal to what he had sent.

Miner uses these output scripts to determine their own balance and then use their updated balance to create new input scripts.

Using these output scripts one can verify if the balance of the miner in the input script is correct or not. They just have to add the amount in the output scripts and compare with the amount int the input script.

Alright, let's create a wallet.

Create a separate folder wallet in the root directory and add a index.js file where we will create our wallet class.

Our wallet will have 3 main properties, the balance, a key pair, and the publicKey. To test our app will start with an initial balance of 500. To do that neatly, let's add a constant in the config.js and call it INITIAL_BALANCE and require this in our wallet class.

The Wallet

The wallet

To create a key pair (public key and private key ) we’ll use a module called elliptic. Let's install it.

npm i elliptic --save

Let's create a new file called chain-util.js in the root directory, which will hold the functions related to cryptocurrency. We’ll use this module that we just installed, we’ll use the use the ec curve based algorithm in our app. So in chainUtil.js require ec algorithm from elliptic and create an instance using secp256k1 since bitcoin uses the same.

const EC = require('elliptic').ec;

const ec = new EC('secp256k1'); // secp256k1 is the algorithm to generate key pair

Let's create a function in the chainUtil class which we will be using in our app to generate the key pair.

class ChainUtil{ static genKeyPair(){

return ec.genKeyPair();

}

} module.exports = ChainUtil;

Now we can use this function in our wallet class, and use the getPublic() function to get the public an encode it to hexadecimal format.

this.keyPair = ChainUtil.genKeyPair(); this.publicKey = this.keyPair.getPublic().encode('hex');

Each transaction needs a unique id. To generate these unique numbers we will use a module called uuid

npm i uuid --save

Let's create an instance of this module in the chain-util.js file.

const uuidV1 = require('uuid/v1'); // version 1 use timestamp to generate unique ids

Let's create a function to generate ids.

static id(){

return uuidV1();

}

Alright. With unique IDs, we can now make our transaction class.

Let's create a file transaction.js in the wallet directory. We’ll need an instance of the chainUtil class.

We’ll make a class Transaction with the id, input, and output as the properties.

const ChainUtil = require('../chain-util'); class Transaction{

constructor(){

this.id = ChainUtil.id();

this.input = null;

this.outputs = [];

}

} module.exports = Transaction;

Input will be an object and output can be multiple so its array of object.

Let's create a function to create a transaction. This function will take the sender’s wallet’s instance, the amount to send and the recipient's address.

It will check if the sender has enough balance and then push an output script in the outputs array. The output script will contain the amount and the address of the receiver.

static newTransaction(senderWallet,recipient,amount){ if(amount > senderWallet.balance){

console.log(`Amount : ${amount} exceeds the balance`);

return;

} // call to the helper function that creates and signs the

// transaction outputs return transaction.outputs.push(...[

{amount: senderWallet.balance -amount,address:

senderWallet.publicKey},

{amount: amount,address: recipient}

]);

}

Our transaction now needs an input object. We’ll use the wallets key pair to sign the transaction and add the signature in the input object along with the other relevant information.

Let's add a sign function in the wallet/index.js file

sign(dataHash){ return this.keyPair.sign(dataHash); }

We’ll use this function in the transaction.js file when we create a new transaction. Let's add a function in the transaction class called signTransaction() This function will take transaction and senders wallet’s instance and create a signed input in the transaction.

Note that we are using hashing function quite a number of times. We can abstract this out into chain-util.js to make our code more reusable. Let's create a hash(data) function in chainUtil and use this instead of directly using SHA256

static hash(data){ return SHA256(JSON.stringify(data)).toString(); }

Let's also make these changes in the block.js file.

Alright next we will create the signTransaction(senderWallet,transaction) function in transaction.js

Now in the newTranasaction() function, we can call signTransaction() with parameter as the current transaction and the sender's wallet.

We also need the functionality to verify the authenticity of the transactions.

Let's create a verify transaction function that will verify the hash and the digital signature of the transaction.

To verify a signature we need to decrypt it using the public. ec provides this functionality inbuilt. Let's create a function verifySignature() in the chainUitl class which we will use later.

static verifySignature(publicKey,signature,dataHash){ return ec.keyFromPublic(publicKey,'hex').verify(dataHash,signature); }

Now in the Transaction class lets create a function called verifyTransaction() where we’ll use the verifySignature function we just created.

Cool.

There is one more thing we are left to do. Imagine a scenario in which you make a transaction in the system but it is not yet sent or added to a block ( it means it is present in the transaction pool). In the meantime, you make another transaction to some other person but this time you created a different transaction. Note that we already have a transaction which is not yet sent, we can optimize the process by updating the outputs and regenerating the signature.

Now we will make an update() function which will find the senders output, update the amount, create a new output and sign the updated transaction.

Brilliant!

Here’s the transaction.js file that we have created so far.

Let's test our wallet and transactions. Create a transction.test.js file in the wallet directory and add a few test cases.

Run the jest test runner and now you’ll see 20 tests passing. Awesome!

We have implemented transactions in our blockchain.

In the next post, we’ll add transaction pool to our blockchain.

Part 7: Implementing Blockchain and Cryptocurrency with PoW consensus algorithm