Blockchain

Build a p2p network and release your cryptocurrency – DEV Community

Hi all, in the previous article, I have covered how to create a simple transaction system for our blockchain. So today, I will build the core component of our cryptocurrency – the peer-to-peer (p2p) network. It’s not only required for a blockchain to work, but after building it, we can really release our coins! Yes, we are at that stage already.

I have also created a tutorial on Youtube, check it our for better understanding.

What is a p2p network?

First, we have to understand what is a peer-to-peer network. In the last parts, I have talked about it a few times, but it’s not really ideal yet, so I will dig deeper about it in this article.

Before we get on to that, we need to understand the client-server model first. In our life, pretty much everything we use currently follows the client-server model. The network works by having a server, and every machines will connect to that server. You can send requests to the server, and the server can send back responses. Think of the system as a company, and the boss is the server. The boss is the one who makes decisions and controls every action of the application.

Image description

But in a distributed peer-to-peer model, machines (called nodes) can send messages to each other without having any 3rd-party system involved. Think of it as a group of friends working together. People can work independently, and decisions will be made by the majority.

Image description

In a cryptocurrency’s network, people should be able to at least send transactions and suggest new blocks.

Without futher ado, let’s code!

What and how we are trying to achieve

We would need a network where nodes can connect with and send messages to each other in a peer to peer fashion. After that, we will add functionalities like broadcasting transactions, suggesting new blocks, send the chain and chain’s information.

I will be using WebSocket – a TCP-based protocol, please learn about it to have a better understanding with what I will be doing.

Also, please read the comments in the code, I use them to explain individual functionalities.

Setup

I will use a light package called ws just to stay simple in this article.

Simply install it using npm:

Basic concepts of ws

A basic node

Create a new file, call it anything you want.

Basically, we will have the basic variables for PORT, the list of peers we are connecting (PEERS), our address (MY_ADDRESS).

I use process.env.abcxyz so that you can configure the node easily through command line.

The MINTING address should never be changed, and we are going to change the old genesis block too:

We are releasing coins and send it to a guy with the address above, which is basically just from this private key: 62d101759086c306848a0c1020922a78e8402e1330981afe9404d0ecc0a4be3d

Remember to replace the old mint key pair with the new one too.

Now, let’s have a way to connect to other nodes, as well as listen to other nodes’ connections.

To implement this system, we need a function to connect, and use server.on(“connection”) for listening to connections.

The connect function should be able to connect to an address, then send it our address, then, the connection handler of that address will connect to our address using the message given.

A message is a string, in this case, a JSON, which have a form like this:

What we need in this case is:

I will create a function to generate messages for convenience:

Now, let’s implement the main system:

To actually do stuff in the future, we would want to store connected sockets and addresses into one array. Also, by doing this, we can send other nodes the address of the node that has just been connected to us.

To connect to all prefixed peers, you can add this line in:

Integrate our blockchain into the network.

What do we need to do?

Alright, now that we have our node running, let’s start diving into the real deal part of the article – cryptocurrency. To create a cryptocurrency, we would need to be able to broadcast transactions, suggest newly mined blocks. New nodes should be able to ask other nodes for their chains too.

0. Adding necessary stuff

Because when we send messages, we are effectively parsing objects to JSON, meaning that the methods of an object (in this case, they are the transactions, blocks, blockchains) will disappear. We can solve this problem by making our methods static, so we can re-use them without having to touch the real objects themselves.

And in the previous article, the validation methods of blocks and transactions are not really ideal, so let’s update them while we are turning everything static.

Related methods

1. Transactions

First, I will create a handy-dandy sendMessage function to send messages to nodes easier.

Now, let’s handle the messages!

A message for broadcasting transactions will look like this:

In our message handler, we will create a new case which simply uses the handy-dandy addTransactions method we have created in the last part.

And you can send a transaction like this:

2. Mining and sending new blocks

Now, let’s handle the new block’s suggestion messages.

This is by far the hardest, most bulky part to implement, so let’s get going shall we?

The message will look like this:

How would we handle this message? The simplest thing we would do first is to check if the block is valid or not, then we will add it to the chain and update the difficulty. The block is valid when:

  • It has valid transactions (the transactions are in our transaction pool, the transactions are valid according to our old methods).
  • It has a valid hash (matches with the block’s information (also called “block header”)).
  • It has a valid difficulty (it can’t be greater or less than difficulty plus/minus 1).
  • It has a valid timestamp (must not be greater than the time they sent us and less than the previous block’s timestamp). This is not really a fulfill way to adjust difficulty, but at least it shouldn’t create too much damage.

But turns out, there’s one really dangerous problem. If one miner mines a block, he wouldn’t really know if his block came first or the other one sent to him came first. Yes, this does happen due to many impacts, one of them is internet problem. Imagine if someone mined a block before you, and he had sent the block to other nodes already, but due to some internet problem, you can manage to finish mining the block after the message is received, so the block sent will be invalid, but it’s in fact valid and you will be left behind.

There are many approaches to this, but I have coined out a really simple system which leverages the use of majority’s support.

We can affectively implement this functionality using a boolean variable called checking and setTimeout. Basically, the idea is that if the block’s prevHash is equal to the latest block’s prevHash, then it’s probably a block that needs checking for replacement. We will set checking to true to indicates that we are checking, then, we will request other nodes for their latest block. We will wait for a period of time (which I have set to 5s) using setTimeout, then we will set checking to false, cancelling the process, and the block that appeared the most is likely the block we need. I will also implement a system to skip on all similar blocks after we have had the correct answer.

Note that the upper code is more of a proof-of-concept, we often would like to check if the block is valid or not just to be safer. There are faster, cleaner, more secure ways than this, but this should do our job.

Let’s create a way to handle TYPE_REQUEST_CHECK. We will send back TYPE_SEND_CHECK, so let’s make one for that as well.

The message will look like this:

The handler:

So the handler is finally done!

You can mine blocks like this:

3. Sending chains

For new nodes that have just joined the network, there are 2 ways to get the latest chain. You can either get a chain from a trust-worthy source, or you can ask for the chain in the network. Note that the size of a message is limited, so we won’t be able to send the whole chain, we will send its blocks and information one by one.

We can implement the second solution like this:

Note that you can send request chain to a trust-worthy node, or base on the majority.

Testing in localhost

To test, I will start 2 new consoles with different PORT, MY_ADDRESS, and PRIVATE_KEY. For the first one, I will set our peers to be empty, and the key to be what the initial coin release points to. For the other one, I will set the peer list to be the first node to test if our “handshake” functionality work. Then, I’m going to create a transaction in the first node and mine in the second node. After 10 seconds, we will print out the opened array and the chain.

First node:

Second node:

It should look like this:

Image description

Nodes have connected to each others, the block is mined, the chain is synced!

Releasing our coin (testing publicly)

Simply host a node publicly (by using port forwarding, also, for each router, you would have a different way to do port forwarding, just simply look up online to see what suits your model), using your PC or a VPS hosting service.

I have tested with my friend here:

My node which is the first node: Image description

His node which is the second node: Image description

We have done some port forwarding and connected to each others’ public IP address.

Note that this network is not meant to be production-ready, but this network should be fine for now.

Source code

The full source code used in this article can be found in this Github repo. Or here with JeChain.

Shoutouts

I want to give appreciation to my friend Apple who have contributed to the code used in the article, and Trey – a really cool guy who enlightens me in constructing the network.

  • Check out Apple’s Github account.
  • Check out Trey’s website.

Contacts

  • My Twitter.
  • My Github.
  • My Youtube channel.

I have also created a tutorial on Youtube, check it our for better understanding.

Related Articles

Back to top button

Adblock Detected

Please consider supporting us by disabling your ad blocker