Skip to content

Commit eb61934

Browse files
committed
Initial commit
0 parents  commit eb61934

File tree

8 files changed

+328
-0
lines changed

8 files changed

+328
-0
lines changed

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
HELP.md
2+
target/
3+
!.mvn/wrapper/maven-wrapper.jar
4+
!**/src/main/**
5+
!**/src/test/**
6+
7+
### IntelliJ IDEA ###
8+
.idea
9+
*.iws
10+
*.iml
11+
*.ipr
12+

pom.xml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.pavlmits</groupId>
8+
<artifactId>blockchain-chat</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
12+
<dependencies>
13+
<dependency>
14+
<groupId>org.apache.commons</groupId>
15+
<artifactId>commons-lang3</artifactId>
16+
<version>3.9</version>
17+
</dependency>
18+
</dependencies>
19+
20+
<build>
21+
<plugins>
22+
<plugin>
23+
<groupId>org.apache.maven.plugins</groupId>
24+
<artifactId>maven-compiler-plugin</artifactId>
25+
<configuration>
26+
<source>11</source>
27+
<target>11</target>
28+
</configuration>
29+
</plugin>
30+
</plugins>
31+
</build>
32+
33+
34+
</project>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.pavlmits.blockchain.chat;
2+
3+
import java.util.ArrayList;
4+
import java.util.Date;
5+
import java.util.List;
6+
import java.util.Random;
7+
8+
public class Block {
9+
10+
private final int id;
11+
private final int magicNumber;
12+
private final int padding;
13+
private final long timestamp;
14+
private final String miner;
15+
private final String currentHash;
16+
private final String previousHash;
17+
private final List<String> messages;
18+
19+
Block(int id, int magicNumber, String previousHash, int padding, long timestamp, String hash, String miner, List<String> messages) {
20+
this.id = id;
21+
this.magicNumber = magicNumber;
22+
this.previousHash = previousHash;
23+
this.padding = padding;
24+
this.timestamp = timestamp;
25+
this.currentHash = hash;
26+
this.miner = miner;
27+
this.messages = new ArrayList<>(messages);
28+
}
29+
30+
int getId() {
31+
return id;
32+
}
33+
34+
String getCurrentHash() {
35+
return currentHash;
36+
}
37+
38+
String getPreviousHash() {
39+
return previousHash;
40+
}
41+
42+
long getTimestamp() {
43+
return timestamp;
44+
}
45+
46+
int getMagicNumber() {
47+
return magicNumber;
48+
}
49+
50+
public String getMiner() {
51+
return miner;
52+
}
53+
54+
public int getPadding() {
55+
return padding;
56+
}
57+
58+
public List<String> getMessages() {
59+
return messages;
60+
}
61+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.pavlmits.blockchain.chat;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
public class Blockchain {
7+
8+
private volatile int lastIdOfABlock;
9+
private volatile int padding;
10+
private volatile List<Block> blocks;
11+
private volatile long previousTimer;
12+
private volatile List<String> messages;
13+
14+
Blockchain() {
15+
this.lastIdOfABlock = 1;
16+
this.padding = 1;
17+
this.previousTimer = 0;
18+
blocks = new ArrayList<>();
19+
messages = new ArrayList<>();
20+
}
21+
22+
public boolean isValid() {
23+
for (int i = 0; i < blocks.size() - 1; i++) {
24+
if (!blocks.get(i + 1).getPreviousHash().equals(blocks.get(i).getCurrentHash()))
25+
return false;
26+
}
27+
return true;
28+
}
29+
30+
void printAll() {
31+
for (Block block : blocks) {
32+
print(block);
33+
}
34+
}
35+
36+
private void print(Block block) {
37+
System.out.println("Block: ");
38+
System.out.println("Created by miner #" + block.getMiner());
39+
System.out.println(block.getMiner() + "gets 100 VC");
40+
System.out.println("Id: " + block.getId());
41+
System.out.println("Timestamp: " + block.getTimestamp());
42+
System.out.println("Magic number: " + block.getMagicNumber());
43+
System.out.println("Hash of the previous block: \n" + block.getPreviousHash());
44+
System.out.println("Hash of the block: \n" + block.getCurrentHash());
45+
if (block.getMessages().isEmpty())
46+
System.out.println("Block data: no messages");
47+
else {
48+
System.out.println("Block data:");
49+
for (String message : block.getMessages()) {
50+
System.out.println(message);
51+
}
52+
}
53+
System.out.println("N was increased to " + block.getPadding());
54+
System.out.println();
55+
}
56+
57+
public synchronized int getIdOfAnewBlock() {
58+
return lastIdOfABlock++;
59+
}
60+
61+
public int getLastIdOfABlock() {
62+
return lastIdOfABlock;
63+
}
64+
65+
public synchronized String getLastBlocksHash() {
66+
if (blocks.isEmpty())
67+
return "0";
68+
return blocks.get(blocks.size() - 1).getCurrentHash();
69+
}
70+
71+
public synchronized void addBlock(String hash, int magicNumber, String minerName, long time) {
72+
Block block = new Block(getIdOfAnewBlock(), magicNumber, getLastBlocksHash(), padding, time, hash, minerName, messages);
73+
blocks.add(block);
74+
calculatePadding(time);
75+
}
76+
77+
//TODO find effective way to calculate padding
78+
private synchronized void calculatePadding(long time) {
79+
if (time <= previousTimer && padding < 5) {
80+
previousTimer = time;
81+
padding++;
82+
messages.clear();
83+
} else {
84+
previousTimer = time;
85+
padding--;
86+
}
87+
}
88+
89+
public int getPadding() {
90+
return padding;
91+
}
92+
93+
public List<String> getMessages() {
94+
return messages;
95+
}
96+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.pavlmits.blockchain.chat;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
public class Main {
7+
public static void main(String[] args) throws InterruptedException {
8+
9+
final Blockchain blockchain = new Blockchain();
10+
Miner miner = new Miner(blockchain);
11+
12+
13+
14+
List<Thread> threads = new ArrayList<>();
15+
for (int i = 0; i < 5; i++) {
16+
Thread thread = new Thread(miner, String.valueOf(i));
17+
thread.start();
18+
threads.add(thread);
19+
}
20+
21+
//TODO create real chat
22+
for (int i = 0; i < 10 ; i++) {
23+
blockchain.getMessages().add("-Message" + i);
24+
Thread.sleep(10);
25+
}
26+
27+
boolean allDead=false;
28+
while(! allDead){
29+
allDead=true;
30+
for (Thread thread : threads)
31+
if (thread.isAlive()) allDead = false;
32+
Thread.sleep(2000);
33+
34+
}
35+
36+
blockchain.printAll();
37+
38+
System.out.println(blockchain.isValid());
39+
40+
//TODO add stage 5
41+
}
42+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.pavlmits.blockchain.chat;
2+
3+
import com.pavlmits.blockchain.chat.util.StringUtil;
4+
import org.apache.commons.lang3.tuple.ImmutablePair;
5+
import org.apache.commons.lang3.tuple.Pair;
6+
7+
import java.util.Date;
8+
import java.util.Random;
9+
10+
public class Miner implements Runnable {
11+
12+
private Blockchain blockchain;
13+
14+
public Miner(Blockchain blockchain) {
15+
this.blockchain = blockchain;
16+
}
17+
18+
@Override
19+
public void run() {
20+
long startTime = System.nanoTime();
21+
Pair<Integer, String> pair = mine();
22+
23+
long endTime = System.nanoTime();
24+
blockchain.addBlock(pair.getRight(), pair.getLeft(), Thread.currentThread().getName(),(endTime - startTime) / 1_000_000_000);
25+
}
26+
27+
private synchronized Pair<Integer,String> mine() {
28+
return calculateHash(blockchain.getLastBlocksHash());
29+
}
30+
31+
32+
private Pair<Integer,String> calculateHash(String previousHash){
33+
int magicNumber = new Random().nextInt(Integer.MAX_VALUE);
34+
String hash = calculateSHA(blockchain.getLastIdOfABlock() + 1, previousHash, magicNumber);
35+
36+
while (!hash.startsWith("0".repeat(blockchain.getPadding()))) {
37+
magicNumber = new Random().nextInt(Integer.MAX_VALUE);
38+
hash = calculateSHA(blockchain.getLastIdOfABlock() + 1, previousHash, magicNumber);
39+
}
40+
41+
return ImmutablePair.of(magicNumber, hash);
42+
}
43+
44+
private String calculateSHA(int id, String previousHash,int magicNumber) {
45+
String input = id + previousHash + new Date().getTime() + magicNumber;
46+
return StringUtil.applySha256(input);
47+
}
48+
49+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.pavlmits.blockchain.chat.util;
2+
3+
public class BlockchainUtil {
4+
5+
//TODO
6+
public void importBlockchain(){ }
7+
8+
public void exportBlockchain(){}
9+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.pavlmits.blockchain.chat.util;
2+
3+
import java.nio.charset.StandardCharsets;
4+
import java.security.MessageDigest;
5+
6+
public class StringUtil {
7+
8+
public static String applySha256(String input){
9+
try {
10+
MessageDigest digest = MessageDigest.getInstance("SHA-256");
11+
/* Applies sha256 to our input */
12+
byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
13+
StringBuilder hexString = new StringBuilder();
14+
for (byte elem: hash) {
15+
String hex = Integer.toHexString(0xff & elem);
16+
if(hex.length() == 1) hexString.append('0');
17+
hexString.append(hex);
18+
}
19+
return hexString.toString();
20+
}
21+
catch(Exception e) {
22+
throw new RuntimeException(e);
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)