DEV Community

Cover image for Building a Blockchain in Go PT: I - The Hello World of Blockchains
Noah Hein
Noah Hein

Posted on • Updated on

Building a Blockchain in Go PT: I - The Hello World of Blockchains

Hello everyone!

I recently have been trying to learn go, and with all of the recent hype around NFT and crypto, I thought instead of learning solidity I would go ahead and power through and continue learning go. However I still wanted the super trendy hip developer kudos for doing something with the blockchain. I looked up some tutorials and then after following them and having a bit of trouble, I thought to share with all of you.

There were two things I was learning throughout this process. They were go and blockchain. If I have learned anything in the time that I have been writing and trying to share knowledge, it is that we should stick to explaining one thing at a time. In light of this newfound wisdom, I will not be teaching you much of the go syntax, as I think it is the easier of the two to grok. Go does have some complex paradigms around channels and routines, but we won't be using that in this tutorial.

I will teach you one thing about golang. We will need to configure go to compile onto our local machine. I am in Windows, and so that is the perspective that you will find here. It honestly should not be different on macOS/Linux as I far as I am aware.

Go Configuration

You will want to install go over here

Normally if you look at a tutorial of Go and how to get it configured you will hear a lot about a GOPATH. This was a big pain and I only figured out afterwards that you do not in fact need to setup all of this. There is a go module system, which works similarly to npm or pip.

All we need to get started is to have go installed at this point.

Now we make a new project folder and sling some code.

mkdir learnBlockChain && cd learnBlockChain

Excellent. Now we can get the go module system going. you can name it whatever you would like, but I would recommend following my format but substituting your username.

go mod init github.com/nheingit/learnBlockChain

This should get you a new file in your project folder called go.mod

//go.mod
1 module github.com/nheingit/learnBlockChain
Enter fullscreen mode Exit fullscreen mode

You will be able to use whatever 3rd party package, and then whenever you use the run command, it will pull in the relevant packages and import them into your project. If you do not have the package already downloaded, it will usually give you the relevant command in the error message. Very neat.
neat gif

Now that we have our mod system configured, you should be able to follow along without doing any importing. You can simply call the method as if it were already part of your project, and it should take care of the rest.

However, if that is not the case, I will put this snippet here as a backup. We are only importing 3 things, so if you get stuck on this portion you can just copy this code and carry on.

Import

//main.go
1 package main
2 
3 import (
4   "bytes"
5   "crypto/sha256"
6   "fmt"
7 )
//rest of code here
//..
//..
//..
Enter fullscreen mode Exit fullscreen mode

Let's Block Out!

Now that the configuration gods have been satiated we may now begin the actual ceremony. Just follow along, and remember that while I am giving you all of the code here, you will learn much more if you type out everything.

You need to build the muscle memory for the go syntax, and to actually think through what it is your code is doing. If you weren't interested in actually learning, you could just go to the git repo and copy paste the code, but you wouldn't gain too much from that.

In your terminal we can runtouch main.go

//go.main

1 package main
2 
3 func main() {
4 
5 }
Enter fullscreen mode Exit fullscreen mode

Now that we have our main.go file ready, we need to reason about what a blockchain is at a lower level. Luckily for us, as with most compound words we can break up the words into their separate parts and divine some meaning from it.

Block

Let us start with the block. Our block from the blockchain will need to consist of three different fields. Since the main appeal of the blockchain is how secure it is, we are going to need some hashing. Hashing wouldn't be particularly useful unless there was some data inside that was worth protecting or preserving in some fashion, so we also need some data. The last element will be how our blocks chain together, so we will also want the previous hash from the block that was before us.

If we translate everything I just said into golang we should come up with something that looks like this

// main.go
type Block struct {
  Hash     []byte
  Data     []byte
  PrevHash []byte
}
Enter fullscreen mode Exit fullscreen mode

Congratulations, you now have a Block®. Well a block by itself is not very useful now is it. Let's get a chain for this sucker and get it goin'!

Chain

The chain portion of a blockchain is just the collection of blocks all together. I think that sounds like a good use case for an array.

// main.go
type BlockChain struct{
  blocks []*Block
}
Enter fullscreen mode Exit fullscreen mode

Excellent! Now you are the proud owner of ye olde block 'n' chain.

But there's a problem now of we can't really do anything with just this. It needs some functionality. I bet a function could help us out with that.

Functions

// All of these functions will be in main.go
Enter fullscreen mode Exit fullscreen mode

I think a useful place to start would be to hash the data that we give the block. We will hash the current data in the block, as well as the block before us, to create a dependency chain. This hashing of the previous block is integral to the dependability of the blockchain. Without this string of connections, we would not be able to verify the integrity of the system programmatically.

func (b *Block) DeriveHash() {
  info := bytes.Join([][]byte{b.Data, b.PrevHash}, []byte{})
  // This will join our previous block's relevant info with the new blocks
  hash := sha256.Sum256(info)
  //This performs the actual hashing algorithm
  b.Hash = hash[:] 
  //If this ^ doesn't make sense, you can look up slice defaults
}
Enter fullscreen mode Exit fullscreen mode

Now that we are able to hash our data how we would like, I think the next step would be to actually use this hashing capability. creating a new block sounds like a great place to flex our sick hashing skills.

func CreateBlock(data string, prevHash []byte) *Block {
    block := &Block{[]byte{}, []byte(data), prevHash}
        //If this is gibberish to you look up
        // pointer syntax in go
    block.DeriveHash()
    return block
}
Enter fullscreen mode Exit fullscreen mode

Great job! We can now create all of the blocks.
However creating many many blocks will not do too many interesting things in this case. We need a blockchain to tie everything together.

func (chain *BlockChain) AddBlock(data string) {
    prevBlock := chain.blocks[len(chain.blocks)-1]
    new := CreateBlock(data, prevBlock.Hash)
    chain.blocks = append(chain.blocks, new)
}
Enter fullscreen mode Exit fullscreen mode

With the ability to AddBlock to the chain, we can start wrapping up here. There is just one catch. We have no way to make the first block in the chain. This is because in all of our functions we are relying upon a PrevHash from the block before us. So we need to create the OG block for the chain.

func Genesis() *Block {
    return CreateBlock("Genesis", []byte{})
}
Enter fullscreen mode Exit fullscreen mode

Last thing we need to do before we're Blockin' 'n' Chainin' to our hearts content is to initialize a new blockchain with the new Genesis block we made.

func InitBlockChain() *BlockChain {
    return &BlockChain{[]*Block{Genesis()}}
}
Enter fullscreen mode Exit fullscreen mode

Now we have all the functionality we need to make a blockchain! that means we get to start writing in our main function. In the vein of "hello world" scope of tutorial for blockchains, I want to print out the fields of all of my Blocks in my BlockChain and call it a day.

func main() {

    chain := InitBlockChain()

    chain.AddBlock("first block after genesis")
    chain.AddBlock("second block after genesis")
    chain.AddBlock("third block after genesis")

    for _, block := range chain.blocks {
        fmt.Printf("Previous hash: %x\n", block.PrevHash)
        fmt.Printf("data: %s\n", block.Data)
        fmt.Printf("hash: %x\n", block.Hash)
    }

}
Enter fullscreen mode Exit fullscreen mode

We now put this in the terminal go run main.go

That should yield you an output of something like this:

Previous hash: 
data: Genesis
hash: 81ddc8d248b2dccdd3fdd5e84f0cad62b08f2d10b57f9a831c13451e5c5c80a5
Previous hash: 
data: first block after genesis
hash: ce6cc03696fed9f5d0f45d0b26fd4f654df50201281be273248e2184e507586e
Previous hash: 
data: second block after genesis
hash: 7e964d1d2887bb2def988d7dfc85d935836d686ce7d101cbcb61716229d74386
Previous hash: 
data: third block after genesis
hash: f5fc87251c9c8d0be886c0d180b42beb9662de3224c2d87df4ee75427655dc45
Enter fullscreen mode Exit fullscreen mode

You should note that you can see that first Genesis block doesn't have a Previous hash, which is why we needed that special functionality.

I hope you enjoyed reading and didn't find anything too easy, or too difficult! I'll close out here by showing a few resources that I used to make this application!

Shoutouts/Resources

the code you should end up with.

If you would like to watch the video where I learned how to do this whole blockchain thing, its right here. You will learn to code this exact project in video form from this excellent gentleman.

Here's the repo: https://github.com/tensor-programming/golang-blockchain

also another great learning resource if you're really trying to get into developing crypto and Ethereum with solidity is DappUniversity

Shoutouts/Resources

If you would like to watch the video where I learned how to do this whole blockchain thing, its right here. You will learn to code this exact project in video form from this excellent gentleman.

Here's the repo: https://github.com/tensor-programming/golang-blockchain

also another great learning resource if you're really trying to get into developing crypto and Ethereum with solidity is DappUniversity

Latest comments (9)

Collapse
 
crazyoptimist profile image
crazyoptimist

Thank you for the great content!
This is the most straight educational blockchain POC over the internet I've seen so far(as a gopher).

Collapse
 
nheindev profile image
Noah Hein

Thank you so much! I'm glad you liked it. Building this out really helped me understand blockchain fundamentals and how everything is connected.

Collapse
 
abhishekverma8954 profile image
Abhishek Verma

I am a beginner. So can you tell me, how I became good ethereum blockchain developer.

Collapse
 
nheindev profile image
Noah Hein

Well it seems like you're in the right place. Learning about how the blockchain works gives you a good foundation to learn higher abstraction concepts.

Collapse
 
abhishekverma8954 profile image
Abhishek Verma

Is there any free course in ethereum blockchain so that I learn better. Because I learn all the basic fundamentals of blockchain but coding part is remain same.

Collapse
 
simonhgao profile image
Simon Gao

Hi, Noah

I have some problems with function "AddBlock"
Why we don't use new := CreateBlock(data, prevBlock.Hash)?
I think the hash of new obj should be pre-block's hash , is that right?

Collapse
 
nheindev profile image
Noah Hein

That is correct, it looks like I mistyped that! Right now it is prevBlock.prevHash, when the correct one would be what you mentioned: prevBlock.Hash

Nice catch 🙏

Collapse
 
sonic0588 profile image
Eugeniy Orlov

Hi, Noah

Thank you for the article. I noticed that "Previous hash" field is empty in the last picture. I think it might relate to mistyping in the CreateBlock function from a previous comment because Previous hash was assigned as a hash of the genesis block.

Thread Thread
 
nheindev profile image
Noah Hein

That is correct. That's why the Prev hash field is blank on ALL of them. It should only be on the first block. As you move forward in the series this issue is rectified.