-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBlocksSimulator.java
More file actions
110 lines (93 loc) · 3.44 KB
/
BlocksSimulator.java
File metadata and controls
110 lines (93 loc) · 3.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package byteblocks;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import static byteblocks.DataGenerator.randomName;
public class BlocksSimulator {
private static class Block {
private String hash;
private long blockHeight;
private String prevHash;
private long timestamp;
private String data;
private String nonce;
public String encodedData() {
return String.format("%s|%s|%s|%s|%s", blockHeight, prevHash, timestamp, data, nonce);
}
}
public static void printBlock(Block block, boolean isLast) {
String blockTitle = "Block " + Instant.ofEpochMilli(block.timestamp);
System.out.println(blockTitle + " (Height: " + block.blockHeight + ")");
System.out.println("├─ Hash: " + block.hash + "...");
System.out.println("├─ Previous Hash: \"" + block.prevHash + "\"");
System.out.println("└─ Data: \"" + block.data + "\"");
if (!isLast) {
System.out.println(" │");
System.out.println(" ▼");
}
}
private static Block genesisBlock() {
Block block = new Block();
block.timestamp = System.currentTimeMillis();
block.blockHeight = 0;
block.prevHash = "";
block.data = "Genesis";
return block;
}
private static Block newBlock(Block prev, String data) {
Block block = new Block();
block.timestamp = System.currentTimeMillis();
block.blockHeight = prev.blockHeight + 1;
block.prevHash = prev.hash;
block.data = data;
return block;
}
public static void minerProofOfWork(Block block) throws NoSuchAlgorithmException {
int nonce = 0;
MessageDigest digest = MessageDigest.getInstance("SHA-256");
while (true) {
block.nonce = Long.toString(nonce);
String encodedData = block.encodedData();
byte[] encodedHash = digest.digest(encodedData.getBytes(StandardCharsets.UTF_8));
String hash = bytesToHex(encodedHash);
if (hash.startsWith("00")) {
block.hash = hash;
return;
}
nonce++;
}
}
private static String bytesToHex(byte[] hash) {
StringBuilder hexString = new StringBuilder(2 * hash.length);
for (int i = 0; i < hash.length; i++) {
String hex = Integer.toHexString(0xff & hash[i]);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
private static void simulateWorld() throws Exception {
Block genesis = genesisBlock();
minerProofOfWork(genesis);
printBlock(genesis, false);
List<Block> blocks = new ArrayList<>();
blocks.add(genesis);
int numberOfBlocks = 3;
for (int i = 0; i < numberOfBlocks; i++) {
Block prev = blocks.getLast();
Block current = newBlock(prev, randomName());
minerProofOfWork(current);
printBlock(current, i + 1 == numberOfBlocks);
blocks.add(current);
Thread.sleep(2_000);
}
}
public static void main(String[] args) throws Exception {
simulateWorld();
}
}