C++ blockchain Implementation

A basic C++ blockchain Implementation allowing users to add blocks and verify chain integrity. Learn to create and validate blocks, manage data using vectors, and grasp essential blockchain principles for decentralized system development.

Overview of Blockchain

Blockchain is essentially a distributed ledger that records transactions across a network of computers. Each transaction is stored in a “block,” which is linked to the previous block using cryptographic hashes, forming a chain of blocks — hence the name blockchain.

Implementation Details

We’ll break down our implementation into two main classes: Block and Blockchain.

C++ blockchain implementation

Block Class

A blockchain is a decentralized, distributed ledger that records transactions across a network of computers. It is the underlying technology behind cryptocurrencies like Bitcoin and Ethereum. A blockchain consists of a series of blocks, each containing data, a timestamp, and a unique hash that links it to the previous block.

The Block class represents an individual block in the blockchain. Here are its key attributes and methods:

  • Attributes:
    • index: The index or position of the block in the chain.
    • timestamp: The time when the block was created.
    • previousHash: The hash of the previous block in the chain.
    • hash: The hash of the current block, calculated based on its data and other attributes.
    • data: Data stored in the block, such as transaction details.
  • Methods:
    • calculateHash(): Calculates the hash of the block using a simple hashing function.
    • simpleHash(): A static method for computing a hash using C++’s std::hash.

You can get the C++ blockchain Code from my GitHub repository

Or by downloading the zip file

C++ Blockchain Class

The Blockchain class manages the chain of blocks. It includes methods to create the blockchain, add new blocks with user-provided data, validate the chain, and retrieve the blockchain data.

  • Attributes:
    • chain: A vector that holds all blocks in the blockchain.
  • Methods:
    • createGenesisBlock(): Creates the first block in the blockchain (genesis block).
    • getLatestBlock(): Retrieves the most recent block in the chain.
    • addBlock(std::string data): Adds a new block to the chain with the provided data.
    • isChainValid(): Validates the blockchain by checking block hashes and previous block hashes.
    • getChain(): Retrieves the entire blockchain for display purposes.
  • Constructor:
    • Initializes the block with an index, data, and the hash of the previous block (prevHash).
    • Sets the timestamp to the current time using time(nullptr).
    • Calculates the hash of the block using calculateHash().
Block(int idx, std::string data, std::string prevHash) : index(idx), data(data), previousHash(prevHash) {
    timestamp = time(nullptr);
    hash = calculateHash();
}

  • Hash Calculation:
    • Concatenates the block’s attributes into a string.
    • Calls simpleHash() to compute the hash of the concatenated string.
std::string calculateHash() const {
    std::stringstream ss;
    ss << index << timestamp << previousHash << data;
    return simpleHash(ss.str());
}

  • Static Hash Function
    • Uses C++’s std::hash to compute a hash value for a given string.
    • Converts the hash value to a hexadecimal string for readability.
static std::string simpleHash(const std::string& str) {
    std::hash<std::string> hasher;
    auto hash = hasher(str);
    std::stringstream ss;
    ss << std::hex << hash;
    return ss.str();
}

  • Validating the Blockchain:
    • Checks the validity of the blockchain by iterating through all blocks (starting from the second block).
    • Verifies if the hash of each block matches its calculated hash (calculateHash()).
    • Verifies if the previousHash of each block matches the hash of the previous block.
bool isChainValid() const {
    for (size_t i = 1; i < chain.size(); ++i) {
        Block currentBlock = chain[i];
        Block previousBlock = chain[i - 1];

        if (currentBlock.hash != currentBlock.calculateHash()) {
            return false;
        }

        if (currentBlock.previousHash != previousBlock.hash) {
            return false;
        }
    }
    return true;
}

C++ vector implementation

This vector serves as the backbone of the blockchain, storing instances of Block objects in sequence.

  • Each Block encapsulates data, timestamps, and cryptographic hashes linking it to its predecessor, forming a secure and verifiable chain.
  • Methods like addBlock() append new blocks to the vector, while isChainValid() ensures the integrity of the blockchain by verifying hash consistency across blocks.
  • This use of std::vector facilitates efficient management and traversal of the blockchain, essential for maintaining a decentralized ledger system.

Main Function

In the main() function, we create a Blockchain object and add blocks to it using user input. We first prompt the user to enter the number of blocks to add, and store this value in the numBlocks variable.

  • We then loop numBlocks times, and in each iteration, we prompt the user to enter the data for the current block.
  • We create a new block with this data, and add it to the chain using the addBlock() method. After adding all the blocks, we check if the chain is valid using the isChainValid() method, and print the result to the console.
  • Finally, we iterate through the chain and print the details of each block, including its index, data, timestamp, previous hash, and hash.
int main() {
    Blockchain blockchain;
    int numBlocks;
    std::cout << "Enter the number of blocks to add: ";
    std::cin >> numBlocks;
    std::cin.ignore(); // To ignore the newline character left in the input buffer
    for (int i = 0; i < numBlocks; ++i) {
        std::string data;
        std::cout << "Enter data for block " << i + 1 << ": ";
        std::getline(std::cin, data);
        blockchain.addBlock(data);
    }
    std::cout << "Blockchain valid: " << blockchain.isChainValid() << std::endl;
    for (const auto& block : blockchain.getChain()) {
        std::cout << "Index: " << block.index << std::endl;
        std::cout << "Data: " << block.data << std::endl;
        std::cout << "Timestamp: " << block.timestamp << std::endl;
        std::cout << "Previous Hash: " << block.previousHash << std::endl;
        std::cout << "Hash: " << block.hash << std::endl;
        std::cout << "------------------------" << std::endl;
    }
    return 0;
}

Conclusion

This detailed explanation provides insights into how C++ blockchain implementation. The provided code offers a foundational understanding of blockchain concepts, including blocks, hashing, validation, and user interaction. While this implementation is simplified for educational purposes, it lays the groundwork for exploring more advanced blockchain features and applications.

Source code of C++ blockchain Implementation

#include <iostream>
#include <vector>
#include <sstream>
#include <ctime>
#include <functional>

class Block {
public:
    std::string previousHash;
    std::string hash;
    std::string data;
    time_t timestamp;
    int index;
//C++ timestamp implementation
    Block(int idx, std::string data, std::string prevHash) : index(idx), data(data), previousHash(prevHash) {
        timestamp = time(nullptr);
        hash = calculateHash();
    }

    std::string calculateHash() const {
        std::stringstream ss;
        ss << index << timestamp << previousHash << data;
        return simpleHash(ss.str());
    }
//C++ stringstream implementation
    static std::string simpleHash(const std::string& str) {
        std::hash<std::string> hasher;
        auto hash = hasher(str);
        std::stringstream ss;
        ss << std::hex << hash;
        return ss.str();
    }
};
//C++ blockchain Implementation
class Blockchain {
public:
    Blockchain() {
        chain.push_back(createGenesisBlock());
    }

    Block createGenesisBlock() {
        return Block(0, "Genesis Block", "0");
    }

    Block getLatestBlock() const {
        return chain.back();
    }

    void addBlock(std::string data) {
        Block newBlock = Block(chain.size(), data, getLatestBlock().hash);
        chain.push_back(newBlock);
    }

    bool isChainValid() const {
        for (size_t i = 1; i < chain.size(); ++i) {
            Block currentBlock = chain[i];
            Block previousBlock = chain[i - 1];

            if (currentBlock.hash != currentBlock.calculateHash()) {
                return false;
            }

            if (currentBlock.previousHash != previousBlock.hash) {
                return false;
            }
        }
        return true;
    }
//C++ vector implementation
    std::vector<Block> getChain() const {
        return chain;
    }
private:
    std::vector<Block> chain;
};
int main() {
    Blockchain blockchain;
    int numBlocks;
    std::cout << "Enter the number of blocks to add: ";
    std::cin >> numBlocks;
    std::cin.ignore(); // To ignore the newline character left in the input buffer
    for (int i = 0; i < numBlocks; ++i) {
        std::string data;
        std::cout << "Enter data for block " << i + 1 << ": ";
        std::getline(std::cin, data);
        blockchain.addBlock(data);
    }
    std::cout << "Blockchain valid: " << blockchain.isChainValid() << std::endl;
    for (const auto& block : blockchain.getChain()) {
        std::cout << "Index: " << block.index << std::endl;
        std::cout << "Data: " << block.data << std::endl;
        std::cout << "Timestamp: " << block.timestamp << std::endl;
        std::cout << "Previous Hash: " << block.previousHash << std::endl;
        std::cout << "Hash: " << block.hash << std::endl;
        std::cout << "------------------------" << std::endl;
    }
    return 0;
}

Leave a comment