Building Layer 1 blockchain from scratch (PART — II Core Blockchain & Mining)

abhiveer singh
3 min readAug 15, 2024

--

Dehradun’s monsoon

This part is in continuation of part 1

In this second part, we’ll focus on building the core blockchain, where we’ll manage transactions, create blocks, and link them to form a chain.

Environment:

Python Version: 3.11.6

Operating System: Linux Ubuntu

Database: LevelDB (from the previous part)

Blockchain (Class)

In Part 1, we created a simple wallet to generate key pairs, sign transactions, and interact with our blockchain. In this part, we will build the core structure of our blockchain. We’ll cover how transactions are collected, blocks are created, and how these blocks are linked together to form a blockchain.

Refer to code here

Code:

1. Importing Required Modules

from typing import Dict, Optional
import json
#Custom Modules
from db import add_transaction as add_tx_to_db, get_latest_state_trie_root
# from p2p import publish
from mine import mine
  • typing: Provides type hints (Dict, Optional) for better code readability and error checking.

2.Blockchain Class Initialization

FILE_NAME = "block.json" #This file is used later to store the blocks
class Blockchain:
def __init__(self):
self.transactions = []
self.blocks = []
self.block_number = 0
  • The Blockchain class is initialized with an empty list of transactions, an empty list of blocks, and a block number starting at zero.

3. Adding a Transaction

def add_transaction(self, transaction: Dict[str, str]) -> Optional[str]:
txn_key = add_tx_to_db(transaction)
if txn_key:
self.transactions.append(transaction)

# Check if we have 10 transactions, then create a block
if len(self.transactions) == 10:
self.create_block()
return txn_key
return None
  • transaction is passed from the wallet code where we built the message.
  • The transaction is first saved to the database using add_tx_to_db.
  • If the transaction is valid and successfully added, it is appended to the self.transactions list.
  • Once the number of transactions reaches 10, create_block is automatically called to create a new block.

4. Creating a Block

 def create_block(self):
self.block_number += 1
# mine function returns the nonce and root.
nonce,root = mine(get_latest_state_trie_root())
block = {
'block_number': self.block_number,
'data': self.transactions,
'nonce': nonce,
'root':root,
'state_root':get_latest_state_trie_root()
}
self.blocks.append(block)
with open(FILE_NAME, "w") as file:
json.dump(block, file, indent=4)
# publish(FILE_NAME)
self.transactions.clear()
  • create_block: Handles the creation of a new block when 10 transactions are accumulated.
  • mine: Mines the block, generating a nonce and updating the root based on the latest state trie.
  • Block storage: The block is saved to a JSON file and also appended to the self.blocks list.
  • Transaction reset: After the block is created, the self.transactions list is cleared to prepare for the next set of transactions.
  • #publish this is where we use P2P connections to publish our block but it is not implemented yet.

Mining

Refer to code here

import hashlib

def mine(latest_root: str) -> (int, str):
nonce = 0
hash_input = latest_root.encode()

while True:
hash_result = hashlib.sha256(hash_input).hexdigest()
if hash_result.startswith("000"):
return nonce, hash_result
nonce += 1
hash_input = hash_result.encode()
print(hash_result)

The mine function accepts a string latest_root, representing the root of the latest block or data to be mined. It initializes a nonce at 0 and encodes the latest_root into bytes. The function then enters an infinite loop where it computes the SHA-256 hash of the hash_input, checks if the resulting hash starts with "000" (a simple proof-of-work condition), and if so, returns the current nonce and the valid hash_result.

If the condition is not met, the nonce is incremented, and the hash_input is updated to the current hash result, with the process repeating until a valid hash is found. The loop also prints each hash as it iterates.

This code exemplifies the fundamental concept of mining, where the goal is to find a nonce that produces a hash satisfying a specific condition, illustrating the proof-of-work mechanism in a straightforward manner.

🏁 Conclusion and What’s Next

In this part, we built a simple blockchain, covering key aspects like transaction management, block creation, and mining. This foundational knowledge sets the stage for exploring more advanced blockchain features in the future parts of this series.

In the next part we will dive into the data base operations of our blockchain

--

--

abhiveer singh

11th Grader | Advancing LLM Security & Agentic Models | Researching Zero-Knowledge Proofs with R1CS & KZG Commitments