Last active
November 13, 2018 02:48
-
-
Save marnix135/ec4f51d07b7854abc56c431deb42b120 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.Date; | |
/* | |
A simple example of a blockchain demonstrating how data stored in it cannot be changed. | |
*/ | |
class Block { | |
private int index; | |
private String timeStamp; | |
private int previousHash; | |
private String[] data; | |
private int hash; | |
public Block(int index, String timeStamp, int previousHash, String[] data) { | |
this.previousHash = previousHash; | |
this.data = data; | |
// Calculate hash when initialising block | |
this.hash = calculateHash(); | |
} | |
public int calculateHash() { | |
// Convert all the stored data into one hash | |
return Arrays.hashCode(new Object[] {index, timeStamp, previousHash, data}); | |
} | |
public int getIndex() { | |
return index; | |
} | |
public void setIndex(int index) { | |
this.index = index; | |
} | |
public String getTimeStamp() { | |
return timeStamp; | |
} | |
public void setTimeStamp(String timeStamp) { | |
this.timeStamp = timeStamp; | |
} | |
public int getPreviousHash() { | |
return previousHash; | |
} | |
public void setPreviousHash(int previousHash) { | |
this.previousHash = previousHash; | |
} | |
public String[] getData() { | |
return data; | |
} | |
public void setData(String[] data) { | |
this.data = data; | |
} | |
public int getHash() { | |
return hash; | |
} | |
public void setHash(int hash) { | |
this.hash = hash; | |
} | |
} | |
class Blockchain { | |
private ArrayList<Block> list = new ArrayList<>(); | |
public Blockchain(Block genesisBlock) { | |
this.list.add(genesisBlock); | |
} | |
public void addBlock(String[] data) { | |
// Add new block with at the end of the chain | |
Block block = new Block(list.size(), new Date().toString(), list.get(list.size() - 1).getHash(), data); | |
list.add(block); | |
} | |
public Block getBlock(int index) { | |
return list.get(index); | |
} | |
public void calculateHashes() { | |
// Calculate the hash for every block | |
list.forEach(Block::calculateHash); | |
} | |
public void check() throws Exception { | |
Block genesisBlock = list.get(0); | |
if (genesisBlock.getHash() != genesisBlock.calculateHash()) { | |
throw new Exception("Block 0 has an incorrect hash!"); | |
} | |
for (int i = 1; i < list.size(); i++) { | |
Block current = list.get(i); | |
Block previous = list.get(i - 1); | |
// The stored hash is not correct | |
if (current.getHash() != current.calculateHash()) { | |
throw new Exception("Block " + i + " has an incorrect hash!"); | |
} | |
// The previous hash is not equal to the hash of the previous block | |
if (current.getPreviousHash() != previous.getHash()) { | |
throw new Exception("Block " + (i - 1) + " has an incorrect hash!"); | |
} | |
} | |
} | |
} | |
public class App { | |
public static void main( String[] args ) { | |
// Initialising the blockchain and the first (genesis) hash | |
Blockchain blockchain = new Blockchain(new Block(0, new Date().toString(), 0, new String[]{"First block", "Some data"})); | |
// Adding 100 more blocks | |
for (int i = 0; i < 100; i++) { | |
blockchain.addBlock(new String[]{i + "th block", "More data"}); | |
} | |
// Changing data, which should throw an error | |
blockchain.getBlock(30).setData(new String[]{"Malicious data."}); | |
blockchain.getBlock(31).setData(new String[]{"More malicious data."}); | |
blockchain.getBlock(32).setData(new String[]{"Even more malicious data."}); | |
// Recalculate hashes and check for errors | |
try { | |
blockchain.calculateHashes(); | |
blockchain.check(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment