Skip to content

Commit e92db11

Browse files
committed
Blockchain in Java: WIP
1 parent 6695287 commit e92db11

File tree

2 files changed

+181
-0
lines changed

2 files changed

+181
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.rampatra.blockchain;
2+
3+
/**
4+
* @author rampatra
5+
* @since 2019-03-05
6+
*/
7+
public class Block {
8+
9+
private int index;
10+
private String previousHash;
11+
private long timestamp;
12+
private String data;
13+
private String hash;
14+
private int nonce;
15+
16+
public Block(int index, String previousHash, long timestamp, String data, String hash, int nonce) {
17+
this.index = index;
18+
this.previousHash = previousHash;
19+
this.timestamp = timestamp;
20+
this.data = data;
21+
this.hash = hash;
22+
this.nonce = nonce;
23+
}
24+
25+
public int getIndex() {
26+
return index;
27+
}
28+
29+
public void setIndex(int index) {
30+
this.index = index;
31+
}
32+
33+
public String getPreviousHash() {
34+
return previousHash;
35+
}
36+
37+
public void setPreviousHash(String previousHash) {
38+
this.previousHash = previousHash;
39+
}
40+
41+
public long getTimestamp() {
42+
return timestamp;
43+
}
44+
45+
public void setTimestamp(long timestamp) {
46+
this.timestamp = timestamp;
47+
}
48+
49+
public String getData() {
50+
return data;
51+
}
52+
53+
public void setData(String data) {
54+
this.data = data;
55+
}
56+
57+
public String getHash() {
58+
return hash;
59+
}
60+
61+
public void setHash(String hash) {
62+
this.hash = hash;
63+
}
64+
65+
public int getNonce() {
66+
return nonce;
67+
}
68+
69+
public void setNonce(int nonce) {
70+
this.nonce = nonce;
71+
}
72+
73+
@Override
74+
public String toString() {
75+
final StringBuilder sb = new StringBuilder("Block{");
76+
sb.append("index=").append(index);
77+
sb.append(", previousHash='").append(previousHash).append('\'');
78+
sb.append(", timestamp=").append(timestamp);
79+
sb.append(", data='").append(data).append('\'');
80+
sb.append(", hash='").append(hash).append('\'');
81+
sb.append(", nonce=").append(nonce);
82+
sb.append('}');
83+
return sb.toString();
84+
}
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.rampatra.blockchain;
2+
3+
import java.nio.charset.StandardCharsets;
4+
import java.security.MessageDigest;
5+
import java.security.NoSuchAlgorithmException;
6+
import java.util.Date;
7+
import java.util.List;
8+
9+
/**
10+
* @author rampatra
11+
* @since 2019-03-05
12+
*/
13+
public class Blockchain {
14+
15+
private List<Block> blockchain;
16+
private int difficulty;
17+
18+
public Blockchain(List<Block> blockchain, int difficulty) {
19+
this.blockchain = blockchain;
20+
this.difficulty = difficulty;
21+
}
22+
23+
public void mine(String data) {
24+
if (blockchain.size() == 0) {
25+
blockchain.add(getGenesisBlock(data));
26+
} else {
27+
Block previousBlock = blockchain.get(blockchain.size() - 1);
28+
blockchain.add(getNextBlock(previousBlock, data));
29+
}
30+
}
31+
32+
private boolean isValidNextBlock(Block previousBlock, Block nextBlock) {
33+
34+
String nextBlockHash = calculateHashForBlock(nextBlock.getIndex(), previousBlock.getHash(),
35+
nextBlock.getTimestamp(), nextBlock.getData(), nextBlock.getNonce());
36+
37+
if (previousBlock.getIndex() + 1 != nextBlock.getIndex()) {
38+
return false;
39+
} else if (!previousBlock.getHash().equals(nextBlock.getPreviousHash())) {
40+
return false;
41+
} else if (!this.isValidHashDifficulty(nextBlockHash)) {
42+
return false;
43+
} else if (!nextBlockHash.equals(nextBlock.getHash())) {
44+
return false;
45+
} else {
46+
return true;
47+
}
48+
}
49+
50+
private Block getGenesisBlock(String data) {
51+
final long timestamp = new Date().getTime();
52+
String hash = calculateHashForBlock(0, "0", timestamp, data, 0);
53+
54+
return new Block(0, "0", timestamp, data, hash, 0);
55+
}
56+
57+
private Block getNextBlock(Block previousBlock, String data) {
58+
final int index = previousBlock.getIndex() + 1;
59+
final long timestamp = new Date().getTime();
60+
61+
final String hash = calculateHashForBlock(index, previousBlock.getHash(), timestamp, data, 0);
62+
return new Block(index, previousBlock.getHash(), timestamp, data, hash, 0);
63+
}
64+
65+
private boolean isValidHashDifficulty(String hash) {
66+
for (int i = 0; i < difficulty; i++) {
67+
if (hash.charAt(i) != '0') {
68+
return false;
69+
}
70+
}
71+
return true;
72+
}
73+
74+
private String calculateHashForBlock(final int index, final String previousHash, final long timestamp,
75+
final String data, final int nonce) {
76+
try {
77+
MessageDigest digest = MessageDigest.getInstance("SHA-256");
78+
byte[] encodedhash = digest.digest(
79+
(index + previousHash + timestamp + data + nonce).getBytes(StandardCharsets.UTF_8));
80+
return bytesToHex(encodedhash);
81+
} catch (NoSuchAlgorithmException e) {
82+
// do nothing for now
83+
}
84+
return "";
85+
}
86+
87+
private static String bytesToHex(byte[] hash) {
88+
StringBuilder hexString = new StringBuilder();
89+
for (int i = 0; i < hash.length; i++) {
90+
String hex = Integer.toHexString(0xff & hash[i]);
91+
if (hex.length() == 1) hexString.append('0');
92+
hexString.append(hex);
93+
}
94+
return hexString.toString();
95+
}
96+
}

0 commit comments

Comments
 (0)