Implementation of blockchain in Java

The blockchain is a digital database based on a distributed ledger system. It works on a five-step process.

  1. End users create transactions and broadcast them to the network.

  2. Then, these unconfirmed transactions are stored in a mempool. The mempool is a storage location inside each fully-validating nodea special type of node that partakes in a consensus that stores unconfirmed transactions in its log.

  3. A record is created by selecting a random set of unconfirmed transactions. A candidate record verification check is done on each record made, and these records are broadcasted to the connected node.

  4. As other nodes receive these records, they will validate it, and if it complies with its protocol rules, it is added to the node's journala personal instance of the ledger. These journals may be different from one another.

  5. Finally, we reach a global representation of the validated set of records. This representation is called a ledger; through it, we can check transactional history.

Data lifecycle in building a consenus.
Data lifecycle in building a consenus.

Implementation

Now we will move to a Java code implementation of the blockchain.

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
class Block {
private int index;
private long timestamp;
private String previousHash;
private List<Transaction> transactions;
private String hash;
private int nonce;
public Block(int index, long timestamp, String previousHash, List<Transaction> transactions) {
this.index = index;
this.timestamp = timestamp;
this.previousHash = previousHash;
this.transactions = transactions;
this.nonce = 0;
this.hash = calculateHash();
}
public String calculateHash() {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
String data = index + timestamp + previousHash + transactions + nonce;
byte[] hashBytes = digest.digest(data.getBytes());
StringBuilder hexString = new StringBuilder();
for (byte hashByte : hashBytes) {
String hex = Integer.toHexString(0xff & hashByte);
if (hex.length() == 1)
hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public String getHash() {
return hash;
}
public String getPreviousHash() {
return previousHash;
}
public String mineBlock(int difficulty) {
String target = new String(new char[difficulty]).replace('\0', '0');
while (!hash.substring(0, difficulty).equals(target)) {
nonce++;
hash = calculateHash();
}
return hash;
}
}

This code snippet shows the Block class. It consists of the following:

  • Lines 9–14: Private member variables.

  • Lines 16–23: Parameterized constructor: It creates a block with the given values from its arguments.

  • Lines 25–42: calculateHash function: It has a try-catch block that, if successful, creates a custom hash key for the block. If not, then it catches and returns the error.

  • Lines 44–50: Getters for current and previous hash.

  • Lines 52–59: mineBlock function: It calculates the hash of the block while updating the nonce.

class Transaction {
private String sender;
private String receiver;
private double amount;
public Transaction(String sender, String receiver, double amount) {
this.sender = sender;
this.receiver = receiver;
this.amount = amount;
}
}

The Transaction class above consists of the following:

  • Lines 2–4: Private member variables.

  • Lines 6–10: Parameterized constructor: It creates a transactional log with the given values from its arguments.

class Blockchain {
private List<Block> chain;
private List<Transaction> pendingTransactions;
private int difficulty;
public Blockchain() {
chain = new ArrayList<>();
pendingTransactions = new ArrayList<>();
difficulty = 2;
createGenesisBlock();
}
private void createGenesisBlock() {
List<Transaction> transactions = new ArrayList<>();
transactions.add(new Transaction("Genesis", "Alice", 100.0));
Block genesisBlock = new Block(0, Instant.now().getEpochSecond(), "0", transactions);
genesisBlock.mineBlock(difficulty);
chain.add(genesisBlock);
}
public void addTransaction(Transaction transaction) {
pendingTransactions.add(transaction);
}
public void minePendingTransactions(String minerAddress) {
Block block = new Block(chain.size(), Instant.now().getEpochSecond(), chain.get(chain.size() - 1).calculateHash(), pendingTransactions);
block.mineBlock(difficulty);
chain.add(block);
pendingTransactions = new ArrayList<>();
pendingTransactions.add(new Transaction("Reward", minerAddress, 1.0));
}
public boolean isChainValid() {
for (int i = 1; i < chain.size(); i++) {
Block currentBlock = chain.get(i);
Block previousBlock = chain.get(i - 1);
if (!currentBlock.calculateHash().equals(currentBlock.getHash()))
return false;
if (!currentBlock.getPreviousHash().equals(previousBlock.getHash()))
return false;
}
return true;
}
private Block getLastBlock() {
return chain.get(chain.size() - 1);
}
}

This is the central portion of the code. The Blockchain class consists of many functions, including:

  • Lines 2–4: Private member variables

  • Lines 6–11: Default Constructor: It initializes a chain of blocks and pendingTransactions. It also sets a block generation difficulty and creates the genesis block.

  • Lines 13–19: createGenesisBlock function: It creates the first block with transactions and adds it to the chain.

  • Lines 21–23: addTransaction function: It adds a transaction to the pendingTransactions list.

  • Lines 33–43: isChainValid function: It checks if the current block has calculated its current and the previous block's hash properly. Based on its conditions, it either returns true or false.

  • Lines 45–47: getLastBlock function: It returns the last block on the chain.

public class Main {
public static void main(String[] args) {
Blockchain blockchain = new Blockchain();
blockchain.addTransaction(new Transaction("Alice", "Bob", 0.5));
blockchain.addTransaction(new Transaction("Bob", "Charlie", 0.3));
blockchain.minePendingTransactions("Miner1");
System.out.println("Is blockchain valid? " + blockchain.isChainValid());
}
}

Finally, the driver code needed to run this code is given above. It creates a new Blockchain and adds transactions to it. Then it mines a block, and depending on its result, it returns whether it is valid.

Q

How are transactions verified in a blockchain network?

A)

By a centralized authority

B)

By a group of miners or validators

C)

By a computer algorithm

D)

By the sender and recipient of the transaction

Conclusion

This was a brief rundown of the Java implementation of blockchain. It is essential to remember that when we run this in a real-world situation, we must remain aware of many other variables like network communication and persistence, as well as consensus algorithms and node functionalities.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved