We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies.

We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies. Less

We use cookies and other tracking technologies... More

Login or register
to publish this job!

Login or register
to save this job!

Login or register
to save interesting jobs!

Login or register
to get access to all your job applications!

Login or register to start contributing with an article!

Login or register
to see more jobs from this company!

Login or register
to boost this post!

Show some love to the author of this blog by giving their post some rocket fuel 🚀.

Login or register to search for your ideal job!

Login or register to start working on this issue!

Login or register
to save articles!

Login to see the application

Engineers who find a new job through Blockchain Works average a 15% increase in salary 🚀

You will be redirected back to this page right after signin

Blog hero image

How to build a blockchain from scratch in Rust

Enoch Chejieh 10 January, 2022 | 5 min read

2021 was a huge year for cryptocurrencies, NFT’s, and decentralized applications (DAPPs), and 2022 will be even bigger. Blockchain is the underlying technology behind all these technologies.

Blockchain technology has the potential to change nearly every aspect of our lives from the Finance industry, Travel & mobility, Infrastructures, Healthcare, Public sector, Retail, Agriculture & mining, Education, Communication, Entertainment, and more.

Every smart person that I admire in the world, and those I semi-fear, is focused on this concept of crypto for a reason. They understand that this is the driving force of the fourth industrial revolution: steam engine, electricity, then the microchip — blockchain and crypto is the fourth. — Brock Pierce

shubham-dhage-R2HtYWs5-QA-unsplash.jpg

What is a blockchain?

A blockchain is a decentralized ledger of transactions across a peer-to-peer network, you can also think of a blockchain like a decentralized database that is immutable. A blockchain can be broken down fundamentally into several components e.g Node, Transaction, Block, Chain, and The consensus protocol (proof of work, proof of stake, proof of history).

If you are anything like me, you learn by building. Now the reason I’m writing this article is to give you a basic overview of how blockchains work by building a blockchain with Rust.

Sounds good? Let’s get to it.

Getting Started

Let us start by creating a new Rust project:

cargo +nightly new blockchain

Change to the directory you just created:

cd blockchain

Let’s add the necessary packages we need to build a blockchain:

[dependencies]
chrono = "0.4"
serde = { version = "1.0.106", features = ["derive"] }
serde_json = "1.0"
sha2 = "0.10.0"

Next, create folder called models, that’s where you will keep most of your blockchain logic. In that folder create two (2) files called blockchain.rs and block.rs.

Import the following packages in both of the files and save them:

Blockchain.rs

use chrono::prelude::*;
// Internal module
use super::block::Block;

Block.rs

use super::blockchain::Blockchain;
use chrono::prelude::*;
use sha2::{Sha256, Digest};
use serde::{Deserialize, Serialize};

If you noticed we imported use super::block::Block; in our blockchain.rs file, we are just importing the struct located in our block.rs file here, don’t worry I will explain that a bit later.

After we have imported the necessary packages let’s create a type in our blockchain.rs file called Blocks:

type Blocks = Vec<Block>;

Next, let’s create a Blockchain type in blockchain.rs and an empty implementation for our Blockchain type:

// `Blockchain` A struct that represents the blockchain.
#[derive(Debug)]
pub struct Blockchain {
  // The first block to be added to the chain.
  pub genesis_block: Block,
  // The storage for blocks.
  pub chain: Blocks,
  // Minimum amount of work required to validate a block.
  pub difficulty: usize
}
impl Blockchain {}

Next, let’s create a Block type in block.rs and an empty implementation for our Block type:

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Block {
   // The index in which the current block is stored.
   pub index: u64,
   // The time the current block is created.
   pub timestamp: u64,
   
   // The block's proof of work.
   pub proof_of_work: u64,
   // The previous block hash.
   pub previous_hash: String,
   // The current block hash.
   pub hash: String
}
impl Block {}

Creating the genesis block:

The genesis block is the first block created in a blockchain. Let’s create a function that creates a genesis block for our blockchain and returns a new instance of the Blockchain type.

Add the following code in our Blockchain implementation in blockchain.rs:

impl Blockchain {
   pub fn new(difficulty: usize) -> Self {
     // First block in the chain.
     let mut genesis_block = Block {
        index: 0,
        timestamp: Utc::now().timestamp_millis() as u64,
        proof_of_work: u64::default(),
        previous_hash: String::default(),
        hash: String::default()
     };
     // Create chain starting from the genesis chain.
     let mut chain = Vec::new();
     chain.push(genesis_block.clone());
     // Create a blockchain Instance.
     let blockchain = Blockchain {
        genesis_block,
        chain,
        difficulty
     };
     blockchain
   }
}

In the code above, we did the following:

  • Created our genesis_block instance.
  • Added the genesis_block we created to the chain in our Blockchain type.
  • Returned an instance of the Blockchain type.

In the genesis_block instance we created, notice how we set our previous_hash key to an empty string value (String::default()) that’s because there would be no previous block since the genesis block is the first block in the blockchain.

Also notice we made the hash of our genesis_block to be an empty string (“”) that’s because we haven’t calculated the hash value for our genesis block yet.

Generating the hash of a block

A hash is generated with the help of cryptography and current information present in the block.

Let's create a function in our block implementation in the block.rs file we created called calculate_hash() :

// Calculate block hash.
pub fn calculate_hash(&self) -> String {
  let mut block_data = self.clone();
  block_data.hash = String::default();
  let serialized_block_data = serde_json::to_string(&block_data).unwrap();
  // Calculate and return SHA-256 hash value.
  let mut hasher = Sha256::new();
  hasher.update(serialized_block_data);

  let result = hasher.finalize();
  format!("{:x}", result)
}

In the code above, we did the following:

  • Converted the block's data to JSON format.
  • Hashed the block's data with the SHA256 algorithm.
  • Returned the hashing result in base16.
Join our newsletter
Join over 111,000 others and get access to exclusive content, job opportunities and more!

Creating a new block

Great!, we have implemented functionalities for creating our genesis block and calculating the block hashes of our blocks.

Now let's add the functionality for adding new blocks to the blockchain, in our blockchain.rs file add this function to the Blockchain type implementation:

pub fn add_block(&mut self, nonce: String) {
  let new_block = Block::new(
    self.chain.len() as u64,
    nonce,
    self.chain[&self.chain.len() - 1].previous_hash.clone()
  );
  new_block.mine(self.clone());
  self.chain.push(new_block.clone());
  println!("New block added to chain -> {:?}", new_block);
}

Here we did the following:

  • Created an add_block function that takes in an argument called &mut self (instance of the Blockchain type).
  • Created our instance of the Block type.
  • Mined a block hash using the Block type's mine function.
  • Added the new block to the chain of blocks.

Next in our block.rs file add the following code in the Block type implementation:

// Create a new block. The hash will be calculated and set automatically.
pub fn new (
 index: u64,
 previous_hash: String,
) -> Self {
   // Current block to be created.
   let mut block = Block {
      index: 0,
      timestamp: Utc::now().timestamp_millis() as u64,
      proof_of_work: u64::default(),
      previous_hash: String::default(),
      hash: String::default(),
   };

   block
}

Here we did the following:

  • Created a function called new() that takes in three arguments index and previous_hash.
  • Created our instance of the Block type.
  • Generated a block hash for our block.
  • Returned an instance of the Block type.

Mining new block

We have successfully implemented functionality for creating a new block.

Let's implement functionality for mining new blocks. The process of mining new blocks involves generating a SHA256 hash that starts with a desired number of 0s which would be the mining difficulty miners have to solve to mine a new block.

Let's create a function in our block.rs file inside our Block type implementation:

// Mine block hash.
pub fn mine (&mut self, blockchain: Blockchain) {
  loop {
    if !self.hash.starts_with(&"0".repeat(blockchain.difficulty)) {
      self.proof_of_work += 1;
      self.hash = self.generate_block_hash();
    } else {
       break
    }
  }
}

Great job, we are done with implementing our blockchain, now let's test it out.

Let's create a file called mod.rs in our models folder and save the following code:

pub mod block;
pub mod blockchain;

All we are doing here is making the files we created earlier blockchain.rs and block.rs publicly accessible in our main.rs file.

Now let's paste the following code in our main.rs file:

mod models;
fn main() {
   let difficulty = 1;
   let mut blockchain = models::blockchain::Blockchain::new(difficulty);

   models::blockchain::Blockchain::add_block(&mut blockchain);
}

Now to initiate a transaction run cargo +nightly run in your terminal.

Conclusion

In this tutorial you've learned how to create a simple blockchain from scratch with Rust.

I hope you've enjoyed reading this article, you can get the full source code of this Rust blockchain here.

Originally published on enoch-chejieh.medium.com

Author's avatar
Enoch Chejieh
Javascript - Rust - Open source - Software Developer

Related Issues

open-editions / corpus-joyce-ulysses-tei
open-editions / corpus-joyce-ulysses-tei
  • Started
  • 0
  • 4
  • Intermediate
  • HTML
open-editions / corpus-joyce-ulysses-tei
open-editions / corpus-joyce-ulysses-tei
  • Started
  • 0
  • 4
  • Intermediate
  • HTML
open-editions / corpus-joyce-ulysses-tei
open-editions / corpus-joyce-ulysses-tei
  • Started
  • 0
  • 5
  • Intermediate
  • HTML
open-editions / corpus-joyce-ulysses-tei
open-editions / corpus-joyce-ulysses-tei
  • Started
  • 0
  • 1
  • Intermediate
  • HTML

Get hired!

Sign up now and apply for roles at companies that interest you.

Engineers who find a new job through Blockchain Works average a 15% increase in salary.

Start with GitHubStart with Stack OverflowStart with Email