Part 2: Networking — Code your own blockchain in less than 200 lines of Go!
Have you checked out Part 1 of this series yet? If not, go take a look. Don’t worry, we’ll wait…
We were stunned at the reception we received in our first “Code your own blockchain in less than 200 lines of Go!” post. What was meant to be a little tutorial for beginning blockchain developers has taken on a life of its own. We’ve been bombarded with requests to do an add-on post where we integrate networking.
The last post showed you how to code up your own blockchain, complete with hashing and validation of each new block. But it all ran in a single terminal (node). How do we get another node to connect to our main instance and have them contribute new blocks, and how do we broadcast the updated blockchain to all the other nodes?
We’ll show you here.
- The first terminal creates a genesis block and a TCP server to which new nodes can connect
- Additional terminals are opened and TCP connections are made to the first terminal
- New terminals write a block to the first terminal
- The first terminal validates the block
- The first terminal broadcasts the new blockchain to each of the new nodes
- All terminals now have synced blockchains!
After the tutorial, try this yourself: have each of the new terminals also act as “First” terminals with different TCP ports and have the other terminals connect to it for a true network!
What you will be able to do
- Run a terminal that provides a genesis block
- Fire up as many additional terminals as you like and have them write blocks to the first terminal
- Have the first terminal broadcast updated blocks to the new terminals
What you won’t be able to do
Like the last post, the aim of this tutorial is to get a basic network of nodes working so you can decide on where your blockchain journey goes from here. You won’t be able to have computers in other networks writing to your first terminal, but this can be readily achieved by putting your binary in the cloud. Also, blockchain broadcasting will be simulated to each of the nodes. Don’t worry, we’ll explain all of this shortly.
Let’s get coding!
Some of this will be a review of the last post. We’ll be using many of the same block generation, hashing and validation functions. But we won’t be using any of the HTTP functionality since we’ll be viewing results in the console and we’ll be using TCP for networking.
What’s the difference between TCP and HTTP?
We won’t get into much detail here but all you need to know is that TCP is a base protocol that transmits data. HTTP is built on top of TCP to utilize this data transmission on the web and in browsers. When you view a website, you’re using HTTP, which is supported by an underlying data transmission protocol, called TCP.
For this tutorial, we’ll be working with TCP as we won’t be needing to view anything in a browser. Go has a nice
net package that provides all the TCP connection functions we need.
Setup, Imports and Review
Some of this will be a review from Part 1. For blockchain generation and validation, we’ll be using the same functions from the last post. Bear with us while we do a quick review. Don’t worry, we’ll get to the new stuff soon!
.env file in your root directory and add the following line:
We store the TCP port number we want to use (in this case 9000) in an environment variable called
If you haven’t done it already, grab the following packages:
go get github.com/davecgh/go-spew/spew to pretty print our blockchain to the console
go get github.com/joho/godotenv to load the variables in our
Create an empty
main.go file. We’ll be putting all our code here.
Let’s do our standard package declaration and write up the imports we’ll need.
The following code snippets are explained in much greater detail in Part 1. Refer to it if you need a refresher. We’ll be moving fast through this.
Let’s create our
Block struct and declare our
Blockchain as a slice of
Now create our hashing function that we need when generating new blocks.
Our block generation function:
Make sure our new block is valid by checking its
Hash of the previous block.
Now we ensure we take the longest chain as the true blockchain:
Nice! We’ve basically got all the blockchain related functions we need with all the HTTP related stuff from Part 1 stripped out. We can now proceed to networking.
Finally! We’re at the good stuff. Let’s set up a network that can pass around new blocks, integrate them into our blockchain, and broadcast new blockchains back to the network.
Let’s start with our main function, as that is a nice abstraction that will help us understand the overall flow.
Right before we do that, let’s declare a global variable called
bcServer (short for blockchain server) under our other struct declarations that is a channel that takes in incoming blocks.
Side note: Channels are one of the most popular features of Go and allow for elegant streamlining of data reading/writing and are most often used to prevent data races. They become particularly powerful when used concurrently, as multiple Go routines can write to the same channel. Traditionally in Java and other C-like language, you’d have to open and close the “gates” for incoming data through mutexes. Channels in Go make this much easier, although there are still places for mutexes in Go. Learn more about channels here.
Now let’s declare our
main function and load up the environment variable from our
.env file that sits in our root directory. Remember, the only environment variable is
ADDR which is our TCP port number 9000 which we’ll use in a second. Also, let’s instantiate our
bcServer in the
Now we need to write up our TCP server. Remember, you can think of TCP servers as being similar to HTTP servers but there is no browser component. All data transmission will be done in the console through our terminal. We will be handling multiple connections to our TCP port. Add this to your
main function below the last line.
This fires up our TCP server at port 9000. It’s important to
defer server.Close() so the connection closes cleanly when we no longer need it. Learn more about
Now we need to create a new connection each time we receive a connection request, and we need to serve it. Add this below the last line.
We just made an infinite loop where we accept new connections. We want to concurrently deal with each connection through a separate handler in a Go routine
go handleConn(conn), so we don’t clog up our
for loop. This is how we can serve multiple connections concurrently.
The perceptive reader will jump up and say, “hey wait! We don’t have a
handleConn function!”. You’re right. But let’s take a quick breather. Nice job, we just wrote up our entire main function. It looks like this:
Let’s write up that
handleConn function now. It only takes in one argument, a nicely packaged
net.Conn interface. Interfaces in Go are amazing and in our opinion, what separates Go from every other C-based language. Concurrency and Go routines get all the hype but interfaces and the fact that they’re satisfied implicitly are the language’s most powerful feature. If you don’t use interfaces in Go yet, get familiar with them as quickly as you can. Interfaces are your next step in your journey to becoming a 10x Go developer!
Put in the skeleton of the function and start it off with a clean
defer statement to close each connection when we’re done with it.
Now we need to allow the client to add new blocks for us to integrate into the blockchain. We’re going to use the same pulse rate from Part 1. Take your own pulse over a minute and keep that number in your head. That will be our BPM (beats per minute).
To achieve the above we need to:
- prompt the client to enter their BPM
- scan the client’s input from
- create a new block with this data, using the
replaceChainfunctions we created previously
- put the new blockchain in the channel we created to be broadcast to the network
- allow the client to enter a new BPM
Here is the code to do that, in the exact order described above.
We create a new scanner. The
for scanner.Scan() loop is tucked away in its own Go routine so it can run concurrently and separately from other connections. We do a quick string conversion of our BPM (which will always be an integer, so we check for that). We do our standard block generation and validation checks and create a new blockchain with the new block.
bcServer <- Blockchain just means we’re throwing our new blockchain into the channel we created. Then we prompt the client to enter a new BPM to create the next block.
We need to broadcast the new blockchain to all the connections being served by our TCP server. Since we’re coding this up on one computer, we’ll be simulating how data gets transmitted to all clients. Under the last line of code, in the same
handleConn function, we need to
- Marshall our new blockchain into JSON so we can read it nicely
- write the new blockchain to the consoles of each of our connections
- set a timer to do this periodically so we’re not getting inundated with blockchain data. This is also what you see in live blockchain networks, where new blockchains are broadcast every X minutes. We’ll use 30 seconds
- Pretty print the main blockchain to the first terminal, just so we can see what’s going on and ensure blocks being added by different nodes are indeed being integrated into the main blockchain
Here is the code, in this exact order.
handleConn function is done. In fact, the whole program is done and we’ve kept it to under 200 lines. That wasn’t bad at all was it?
Check out the completed code here!
blockchain-tutorial - Write and publish your own blockchain in less than 200 lines of Go
The Fun Stuff
Let’s try this baby out! Let’s fire up our application by going to our directory and
go run main.go
As expected, we see our genesis block. What’s happening at the same time is that we’ve started a TCP server at port 9000 that can take in multiple connections. So let’s do that.
Open a new terminal window and connect to our TCP server with
nc localhost 9000 . We’ll be using different color terminals to make it clear these are different clients. Do this a couple times with a couple terminal sessions to activate multiple clients.
Now type in a BPM to any of the clients. And KAPOW! We see the new block added to the first terminal! Networking in action!
Here’s where it gets REALLY cool. Wait 30 seconds. Go to one of the other clients and you’ll see the new blockchain broadcast to all the clients, even if those clients never inputted a BPM!
Congratulations! Not only did you create your own blockchain from the last tutorial, you’ve now added networking ability to it. There are several places you can go from here:
- To have a bigger network running on your local environment, create multiple directories that hold a copy of the application each with different TCP ports. For each terminal session, serve a TCP port and connect to a different one so you can receive and send data.
- Connect data being streamed from multiple ports. This is a topic for another tutorial but is done readily.
This is all a blockchain network is. It needs to take in incoming data and also broadcast data externally. Doing both in a single terminal session is effectively what a mining setup is.
- If you want to try this with you friends, set up the server in the cloud using your favorite hosting provider. Have your friends connect to it and send in data. There are some additional security considerations here. If there is demand we’ll write up a tutorial for this too.
You are well on your way to intimately understanding multiple facets of the blockchain. From here, we’d recommend reading up on consensus algorithms like Proof of Work or Proof of Stake.
Or…you can just wait for us to write a new blog post about it :-)
We released a follow-up on how to store data through the blockchain using IPFS. Take a look here!
We also released another tutorial on how to code your own blockchain mining algorithm here!
Want to learn about Proof of Stake? Check this out.
How to code a simple P2P blockchain in Go! here.
Learn about Byzantine fault tolerance, Turing completeness and other advanced blockchain concepts here.
To learn more about Coral Health and how we’re using the blockchain to advance personalized medicine research, visit our website.
Until next time!