Skip to content

Instantly share code, notes, and snippets.

@felixklauke
Last active November 6, 2018 05:55
Show Gist options
  • Save felixklauke/432552438b3bb7d23137efb78b3d6bc6 to your computer and use it in GitHub Desktop.
Save felixklauke/432552438b3bb7d23137efb78b3d6bc6 to your computer and use it in GitHub Desktop.
BlockChain example.
import org.apache.commons.codec.digest.DigestUtils;
import java.util.Collections;
import java.util.List;
/**
* Represents one block in the chain.
*
* @author Felix Klauke <info@felix-klauke.de>
*/
public class Block {
/**
* The delimiter of the blocks hash. Can by like $ or |.
*/
private static final String HASH_DELIMITER = "$";
/**
* The timestamp when the block was created.
*/
private final long timestamp = System.currentTimeMillis();
/**
* The transactions this block will verify.
*/
private final List<Transaction> transactions;
/**
* The hash of the previous block in the chain.
*/
private final String previousBlockHash;
/**
* The proof that some work was done for earning this block.
*/
private final int proofOfWork;
/**
* Create a new block by its underlying data.
*
* @param previousBlockHash The hash of the previous block in the chain.
* @param transactions The transactions this block will verify.
* @param proofOfWork The proof that some work was done for earning this block.
*/
public Block(String previousBlockHash, List<Transaction> transactions, int proofOfWork) {
this.previousBlockHash = previousBlockHash;
this.transactions = transactions;
this.proofOfWork = proofOfWork;
}
public List<Transaction> getTransactions() {
return Collections.unmodifiableList(transactions);
}
public long getTimestamp() {
return timestamp;
}
public String getPreviousBlockHash() {
return previousBlockHash;
}
public int getProofOfWork() {
return proofOfWork;
}
public String getHash() {
return DigestUtils.sha256Hex(timestamp + HASH_DELIMITER + transactions.toString() + HASH_DELIMITER + previousBlockHash + HASH_DELIMITER + proofOfWork);
}
}
import org.apache.commons.codec.digest.DigestUtils;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
/**
* @author Felix Klauke <info@felix-klauke.de>
*/
public class BlockChain {
/**
* The prefix a proof of work has to have to be valid.
*/
private static final String VALIDATION_PREFIX = "0000000000000000000";
/**
* The transactions the next created block will verify.
*/
private final List<Transaction> transactions = new ArrayList<>();
/**
* All blocks in the chain.
*/
private final Deque<Block> blocks = new LinkedList<>();
/**
* Start mining a new block.
*
* @return The block instance.
*/
public Block mineBlock() {
int proofOfWork = proofOfWork();
Block block = new Block(blocks.getLast().getHash(), transactions, proofOfWork);
transactions = new ArrayList();
return block;
}
/**
* Add a transaction that will be verified by the next block.
*
* @param transaction The transaction.
*/
public void addTransaction(Transaction transaction) {
transactions.add(transaction);
}
/**
* Add a block to the chain.
*
* @param block The block.
*/
public void addBlock(Block block) {
boolean offer = blocks.offer(block);
}
/**
* Generate a new proof of work.
*
* @return The proof of work.
*/
public int proofOfWork() {
return proofOfWork(blocks.getLast().getProofOfWork());
}
private int proofOfWork(int lastProof) {
int proof = 0;
while (!validateProofOfWork(lastProof, proof)) {
proof++;
}
return proof;
}
private boolean validateProofOfWork(int lastProof, int currentProof) {
String result = lastProof + "" + currentProof;
return DigestUtils.sha256Hex(result).startsWith(VALIDATION_PREFIX);
}
}
import java.util.ArrayList;
import java.util.UUID;
/**
* @author Felix Klauke <info@felix-klauke.de>
*/
public class Main {
public static void main(String[] args) {
// Genesis block
Block block = new Block("", new ArrayList<>(), 0);
BlockChain blockChain = new BlockChain();
blockChain.addBlock(block);
blockChain.addTransaction(new Transaction(UUID.randomUUID(), 10, UUID.randomUUID()));
Block mineBlock = blockChain.mineBlock();
System.out.println("Mined block: " + block.getHash());
blockChain.addBlock(block);
}
}
import java.util.UUID;
/**
* @author Felix Klauke <info@felix-klauke.de>
*/
public class Transaction {
private final UUID source;
private final long amount;
private final UUID destination;
public Transaction(UUID source, long amount, UUID destination) {
this.source = source;
this.amount = amount;
this.destination = destination;
}
public UUID getSource() {
return source;
}
public UUID getDestination() {
return destination;
}
public long getAmount() {
return amount;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment