Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/project.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

132 changes: 132 additions & 0 deletions src/blockchain/Block.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package blockchain;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;



class Block implements Serializable{

private List<Message> messagesStack = new LinkedList<>();
private String prevHash;
private String hash;
private int id;
private long timeStamp;
private int magicNumber;
private long maxMsgID;

public Block(Block prevBlock, int difficulty){

if(prevBlock == null) {
this.prevHash = "0";
this.id = 1;
}
else {
this.prevHash = prevBlock.getHash();
this.id = prevBlock.getId() + 1;
}
String zeros = "";
for (int i = 0; i < difficulty; i++){
zeros += "0";
}

do {
setMagicNumber();
this.hash = applySha256(this.prevHash + this.magicNumber);
}while(!this.hash.startsWith(zeros));
setMaxMsgID();
this.timeStamp = new Date().getTime();
}

public void printOutResults() throws UnsupportedEncodingException {
System.out.println("Id: " + this.getId());
System.out.println("Timestamp: " + this.getTimeStamp());
System.out.println("Magic number: " + this.getMagicNumber());
System.out.println("Hash of the previous block:");
System.out.println(this.getPrevHash());
System.out.println("Hash of the block:");
System.out.println(this.getHash());
if (this.id == 1 || messagesStack.isEmpty()){
System.out.println("Block data: no messages");
}else{
System.out.println("Block data: ");
for(Message s: messagesStack) {
String str = new String(s.getList().get(0), "UTF-8");

System.out.println(str);
}
}
}


private void setMagicNumber() {
this.magicNumber = new Random().nextInt(Integer.MAX_VALUE);
}

public int getId() {
return id;
}

public String getHash() {
return hash;
}

public String getPrevHash() {
return prevHash;
}

public long getTimeStamp(){
return timeStamp;
}


public String applySha256(String input){
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
/* Applies sha256 to our input */
byte[] hash = digest.digest(input.getBytes("UTF-8"));
StringBuilder hexString = new StringBuilder();
for (byte i : hash) {
String hex = Integer.toHexString(0xff & i);
if(hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
catch(Exception e) {
throw new RuntimeException(e);
}
}

public int getMagicNumber(){
return this.magicNumber;
}

public void writeMessagesStack(LinkedList<Message> messagesStack){
this.messagesStack.addAll(messagesStack);
}

public LinkedList<Message> getMessageStack(){
return (LinkedList<Message>) this.messagesStack;
}

private void setMaxMsgID(){
long max = 0;
for (Message aMessagesStack : this.messagesStack) {
if (max < aMessagesStack.getId()) {
max = aMessagesStack.getId();
}
}
this.maxMsgID = max;
}

public long getMaxMsgID(){
return this.maxMsgID;
}

}
167 changes: 167 additions & 0 deletions src/blockchain/Blockchain.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package blockchain;

import java.io.*;
import java.util.LinkedList;


class Blockchain {
private LinkedList<Message> messages = new LinkedList<>();
private volatile LinkedList<Block> blockchain = null;
private boolean newFile = false;
private int timeSpent;
private int difficulty = 0;
private static long ids = 1;


public Blockchain(String filePath) {
File file = new File(filePath);//"D:\\hyperskillGit\\blockchain\\MyBlockchain");
readBlockchainFromFile(file);
}

public void readBlockchainFromFile(File file) {
try {
newFile = file.createNewFile();
if (newFile) {
System.out.println("The new blockchain file was successfully created.");
this.blockchain = new LinkedList<>();
this.difficulty = 0;
Blockchain.ids = 1;
} else {
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
this.blockchain = (LinkedList<Block>) ois.readObject();
System.out.println("The Blockchain was read from the file");
ois.close();
fis.close();
if(blockchain.peekLast().getMessageStack().peekLast() != null) {
Blockchain.ids = blockchain.peekLast().getMessageStack().peekLast().getId() + 1L;
}
this.difficulty = getDifficultyFromFile(this.blockchain.peekLast().getHash());
}
} catch (IOException e) {
System.out.println("Cannot create the file: " + file.getPath());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

public void writeBlockchainToFile(String filePath) {
File file = new File(filePath);
try {
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(blockchain);
oos.close();
fos.close();
System.out.println("The Blockchain was successfully written to the file");
System.out.println("");
} catch (FileNotFoundException e) {
System.out.println("File not found");
} catch (IOException e) {
System.out.println("Cannot write to the file");
}
}

public void setDifficulty() {
Block b = this.blockchain.peekLast();
if (b == null) {
this.difficulty = 0;
} else {
if (getTimeSpent() < 10) {
this.difficulty += 1;
System.out.println("N was increased to " + this.difficulty);
} else if (getTimeSpent() >= 60) {
this.difficulty -= 1;
System.out.println("N was decreased to " + this.difficulty);
} else {
System.out.println("N stays the same");
}
}
}

public synchronized int getDifficulty() {
return this.difficulty;
}

public synchronized LinkedList<Block> getBlockchain() {
return this.blockchain;
}

public synchronized boolean addBlock(Block block) {
Block blockPrev = this.blockchain.peekLast();
if (block != null) {
if (blockPrev == null && block.getPrevHash().equals("0")) { //first block
this.blockchain.add(block);
return true;
} else if (blockPrev.getHash().equals(block.getPrevHash())) { //block is valid
this.blockchain.add(block);
return true;
} else {
return false;
}
} else {
return false;
}
}

public synchronized boolean isBlockchainValid() {
int cnt = 0;
if (!this.newFile) {
for (int i = 0; i < this.blockchain.size() - 1; i++) {
if (!this.blockchain.get(i).getHash().equals(this.blockchain.get(i + 1).getPrevHash())) {
cnt++;
}
}
//check that every message has an identifier greater than the maximum identifier of the previous block
for(int i = this.blockchain.size() - 1; i > 0; i--){
for(int j = 0; j < this.blockchain.get(i).getMessageStack().size(); j++) {
if (!(this.blockchain.get(i-1).getMaxMsgID() < this.blockchain.get(i).getMessageStack().get(j).getId()))
{
cnt++;
}
}
}
}
return cnt == 0;
}

private int getDifficultyFromFile(String hash){
int i = 0;
while (hash.charAt(i) == '0'){
i++;
}
return i;
}

public void addMessagesToTheBlockchain(Message msg) throws Exception {
if(msg.getId() < Blockchain.ids) {
if(msg.verifySignature(msg.getList().get(0),msg.getList().get(1))) {
this.messages.add(msg);
}
else {
System.out.println("Signature is wrong");
}
}else{
System.out.println("Messaage rejected");
}
}

public void addMessagesToTheBlock(){
this.blockchain.peekLast().writeMessagesStack(this.messages);
this.messages.clear();
}

public void setTimeSpent(int timeSpent){
this.timeSpent = timeSpent;
}

public int getTimeSpent() {
return timeSpent;
}

public long setMsgID(){
return ids++;
}


}
33 changes: 33 additions & 0 deletions src/blockchain/GenerateKeys.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package blockchain;

import java.security.*;


class GenerateKeys {

private KeyPairGenerator keyGen;

private PrivateKey privateKey;
private PublicKey publicKey;

public GenerateKeys(int keylenth) throws NoSuchAlgorithmException, NoSuchProviderException {
this.keyGen = KeyPairGenerator.getInstance("RSA");
this.keyGen.initialize(keylenth);
}

public void createKeys(){
KeyPair pair;
pair = this.keyGen.generateKeyPair();
this.privateKey = pair.getPrivate();
this.publicKey = pair.getPublic();
}

public PrivateKey getPrivateKey(){
return this.privateKey;
}

public PublicKey getPublicKey() {
return this.publicKey;
}

}
Loading