blockchain

Blockchain is a technology that allows data to be stored and exchanged on a peer-to-peer (P2P) basis. Structurally, blockchain data can be consulted, shared, and secured thanks to consensus-based algorithms. It is used in a decentralized manner and removes the need for intermediaries, or “trusted third parties”

In simple words, Blockchain is a database. What is a database? A database is an organized collection of data. Or, you can say, a data structure that stores the data. Therefore, Blockchain is just a data structure that stores the data. As the name hinted, there will be a chain of blocks.

blockchain
https://www.spheregen.com/blockchain-technology-basics

This basic blockchain has a linked list that is composed of blocks. Each block has the following properties.

  • Index
  • Timestamp
  • Previous Hash
  • Hash
  • Data

Take this blockchain course and become a blockchain developer

Today we are going to build a blockchain in Elixir. We will build everything whatever a basic blockchain provides, concepts are simple and I’m assuming that you are a little familiar with the elixir and blockchain concepts, but even if you are not then I’ll try to explain every detail about blockchain.

We will build blocks, hash, wallets, consensus step by step so in this part we will build a blockchain with having a chain of blocks. Then in later parts, we will see how we can build transactions, mining, and other blockchain-related stuff.

So let’s set up the project quickly and start doing it quickly.

mix phx.new ex_chain --no-html --no-ectoCode language: Elixir (elixir)

This will initialize our application and let’s go into the project and start navigating.

cd ex_chainCode language: Markdown (markdown)

Now, let’s create a new file lib/blockchain/block.ex this will contain the block related functions and logic.

Let’s build the struct for the block, so our block will be having 4 basic things as of now then slowly we will keep adding new stuff as we proceed further.

So let’s say that in a very basic block in a blockchain we have timestamp, hash of block, block data and previous block hash . So let’s add it to the block.

defmodule ExChain.BlockChain.Block do
  @moduledoc """
    This module is the single block struct in a blockchain
  """
    alias __MODULE__

  @type t :: %Block{
          timestamp: pos_integer(),
          last_hash: String.t(),
          hash: String.t(),
          data: any()
        }
        
  defstruct ~w(timestamp last_hash hash data)a
 endCode language: Elixir (elixir)

So this will give us a basic block struct, which has details about the block.

Let’s add some basic functions into the block.ex by which we can create new blocks and a genesis block (Genesis Block is the first block in any blockchain), Genesis block doesn’t have any previous hash in it so we will leave the previous hash field empty.

So let’s add some tests first then we will implement the functions to pass those tests. create a file in test/blockchain/block_test.exs

defmodule ExChain.Blockchain.BlockTest do
  @moduledoc """
  This module contains test related to a block
  """

  use ExUnit.Case
  alias ExChain.BlockChain.Block

  describe "block" do
    test "genesis is valid" do
      assert %Block{
               data: "genesis data",
               hash: "genesis-hash",
               last_hash: "-",
               timestamp: 1_599_909_623_805_627
             } == Block.genesis()
    end

    test "new give a new block when we pass the parameters" do
      # setup the data
      timestamp = DateTime.utc_now() |> DateTime.to_unix(1_000_000)
      data = "this is new block data"
      last_hash = "random_hash_last_block"
      
      assert %Block{timestamp: ^timestamp, hash: hash, last_hash: ^last_hash, data: ^data} =
               Block.new(timestamp, hash, last_hash, data)
    end
  end
endCode language: Elixir (elixir)

Now run mix test both tests will fail so let’s write the functions so that it can pass.

Let’s modify the lib/blockchain/block.ex with the following functions.

defmodule ExChain.BlockChain.Block do
  @moduledoc """
  This module is the single block struct in a blockchain
  """

  alias __MODULE__

  @type t :: %Block{
          timestamp: pos_integer(),
          last_hash: String.t(),
          hash: String.t(),
          data: any()
        }

  defstruct ~w(timestamp last_hash hash data)a

  @spec new(pos_integer(), String.t(), any()) :: Block.t()
  def new(timestamp, hash, last_hash, data) do
    %__MODULE__{timestamp: timestamp, last_hash: last_hash, hash: hash, data: data}
  end

  @spec genesis() :: Block.t()
  def genesis() do
    __MODULE__.new(1_599_909_623_805_627, "genesis-hash", "-", "genesis data")
  end
endCode language: Elixir (elixir)

Here we have created 2 new functions in which are new/4 and genesis/0 and now our tests should pass.

Our next task is to create the mine function and adding the hash functions so that our data which we have passed can be validated and we can build the foundations of the hash.

Now we will add the function hash/3 which will accept timestamp, last_hash and data so that we can get the current block hash. So let’s modify the tests and functions.

defmodule ExChain.BlockChain.Block do
  @moduledoc """
  This module is the single block struct in a blockchain
  """

  alias __MODULE__

  @type t :: %Block{
          timestamp: pos_integer(),
          last_hash: String.t(),
          hash: String.t(),
          data: any()
        }

  defstruct ~w(timestamp last_hash hash data)a

  @spec new(pos_integer(), String.t(), any()) :: Block.t()
  def new(timestamp, last_hash, data) do
    hash = hash(timestamp, last_hash, data)
    %__MODULE__{timestamp: timestamp, last_hash: last_hash, hash: hash, data: data}
  end

  @spec genesis() :: Block.t()
  def genesis() do
    __MODULE__.new(1_599_909_623_805_627, "-", "genesis data")
  end

  def mine_block(%__MODULE__{hash: last_hash}, data) do
    __MODULE__.new(get_timestamp(), last_hash, data)
  end

  # private functions
  defp get_timestamp(), do: DateTime.utc_now() |> DateTime.to_unix(1_000_000)

  defp hash(timestamp, last_hash, data) do
    data = "#{timestamp}:#{last_hash}:#{Jason.encode!(data)}"
    Base.encode16(:crypto.hash(:sha256, data))
  end
endCode language: Elixir (elixir)
defmodule ExChain.Blockchain.BlockTest do
  @moduledoc """
  This module contains test related to a block
  """

  use ExUnit.Case
  alias ExChain.BlockChain.Block

  describe "block" do
    test "genesis is valid" do
      assert %Block{
               data: "genesis data",
               hash: "F277BF9150CD035D55BA5B48CB5BCBE8E564B134E5AD0D56E439DD04A1528D3B",
               last_hash: "-",
               timestamp: 1_599_909_623_805_627
             } == Block.genesis()
    end

    test "mine block returns new block" do
      %Block{hash: hash} = genesis_block = Block.genesis()

      assert %Block{
               data: "this is mined data",
               last_hash: ^hash
             } = Block.mine_block(genesis_block, "this is mined data")
    end

    test "new give a new block when we pass the parameters" do
      # setup the data
      timestamp = DateTime.utc_now() |> DateTime.to_unix(1_000_000)
      last_hash = "random_hash"
      data = "this is new block data"

      assert %Block{timestamp: ^timestamp, hash: _hash, last_hash: ^last_hash, data: ^data} =
               Block.new(timestamp, last_hash, data)
    end
  end
endCode language: Elixir (elixir)

Here we have modified the existing functions to generate block hash from the new/3 function and return us back the fresh %Block{} struct.

We have added a mine_block/2 the function which mines the new blocks when we give the last_hash so it sets the params accordingly and creates the new blocks.

Let’s stop this part over here and in the next part, we will create the blockchain from these blocks.

Here is the link for the second post link

Also, Read

I hope you have enjoyed this article. If you liked it, consider buying a coffee here … Thank You


Leave a Comment

Your email address will not be published. Required fields are marked *