Blockchain 12 min read

Building a Simple Java Blockchain: Code Walkthrough & Core Concepts

This article explains blockchain fundamentals and demonstrates a Java implementation, covering block structure, immutability, hashing, Merkle trees, transaction handling, proof‑of‑work mining, and unit tests with complete code examples.

21CTO
21CTO
21CTO
Building a Simple Java Blockchain: Code Walkthrough & Core Concepts

Blockchain technology, popularized by Bitcoin, is gaining traction across industries. This tutorial focuses on the architecture of a blockchain, especially the "append‑only, immutable" distributed ledger, and shows how to realize these concepts in Java.

Simple Blockchain Overview

A block contains header information and a set of transactions. The chain starts with a genesis block; new blocks are created when the transaction count reaches a predefined threshold.

Immutability

Blocks are immutable because each block’s content is hashed with SHA‑256, producing a unique identifier. The hash of the previous block is stored in the current block’s header, making tampering practically impossible with current computing power.

Block Class Definition (Java)

public class Block<T extends Tx> {
    public long timeStamp;
    private int index;
    private List<T> transactions = new ArrayList<T>();
    private String hash;
    private String previousHash;
    private String merkleRoot;
    private String nonce = "0000";
    // caches Transaction SHA256 hashes
    public Map<String,T> map = new HashMap<String,T>();
    // ... other methods ...
}

Hash Calculation

Each block can compute its hash by combining its fields and the serialized transaction list.

public void computeHash() {
    Gson parser = new Gson(); // usually cached
    String serializedData = parser.toJson(transactions);
    setHash(SHA256.generateHash(timeStamp + index + merkleRoot + serializedData + nonce + previousHash));
}

SimpleBlockchain Class

public class SimpleBlockchain<T extends Tx> {
    public static final int BLOCK_SIZE = 10;
    public List<Block<T>> chain = new ArrayList<Block<T>>();
    public SimpleBlockchain() {
        // create genesis block
        chain.add(newBlock());
    }
    // ... other methods ...
}

Creating a New Block

public Block<T> newBlock() {
    int count = chain.size();
    String previousHash = "root";
    if (count > 0) {
        previousHash = blockChainHash();
    }
    Block<T> block = new Block<T>();
    block.setTimeStamp(System.currentTimeMillis());
    block.setIndex(count);
    block.setPreviousHash(previousHash);
    return block;
}

Adding and Validating Blocks

public void addAndValidateBlock(Block<T> block) {
    Block<T> current = block;
    for (int i = chain.size() - 1; i >= 0; i--) {
        Block<T> b = chain.get(i);
        if (b.getHash().equals(current.getPreviousHash())) {
            current = b;
        } else {
            throw new RuntimeException("Block Invalid");
        }
    }
    this.chain.add(block);
}

Chain Validation

public boolean validate() {
    String previousHash = null;
    for (Block<T> block : chain) {
        String currentHash = block.getHash();
        if (!currentHash.equals(previousHash)) {
            return false;
        }
        previousHash = currentHash;
    }
    return true;
}

Merkle Tree

Transactions are hashed and combined pairwise up the tree until a single Merkle root remains, which is stored in the block header.

Merkle tree illustration
Merkle tree illustration

Proof‑of‑Work Mining

Mining finds a nonce that makes the block hash start with a required number of leading zeros.

private String proofOfWork(Block block) {
    String nonceKey = block.getNonce();
    long nonce = 0;
    boolean nonceFound = false;
    String nonceHash = "";
    Gson parser = new Gson();
    String serializedData = parser.toJson(transactionPool);
    String message = block.getTimeStamp() + block.getIndex() + block.getMerkleRoot() + serializedData + block.getPreviousHash();
    while (!nonceFound) {
        nonceHash = SHA256.generateHash(message + nonce);
        nonceFound = nonceHash.substring(0, nonceKey.length()).equals(nonceKey);
        nonce++;
    }
    return nonceHash;
}

Unit Tests

The project includes JUnit tests that verify block creation, hashing, Merkle tree generation, and proof‑of‑work functionality. Screenshots of the test results are shown below.

JUnit test results
JUnit test results

Conclusion

The example demonstrates how a basic Java blockchain works, from block structure and immutability to transaction handling, Merkle trees, and proof‑of‑work mining. Readers are encouraged to explore production‑grade frameworks such as BitcoinJ, Hyperledger Fabric, or other open‑source projects.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaMerkle Treesmart contractsProof of Workimmutability
21CTO
Written by

21CTO

21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.