File tree Expand file tree Collapse file tree 6 files changed +108
-0
lines changed
src/main/kotlin/com/baeldung/chain Expand file tree Collapse file tree 6 files changed +108
-0
lines changed Original file line number Diff line number Diff line change
1
+ ## Relevant Articles
Original file line number Diff line number Diff line change
1
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
2
+ <project xmlns =" http://maven.apache.org/POM/4.0.0" xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
3
+ xsi : schemaLocation =" http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
4
+ <modelVersion >4.0.0</modelVersion >
5
+ <artifactId >kotlin-blockchain</artifactId >
6
+ <name >kotlin-blockchain</name >
7
+ <packaging >jar</packaging >
8
+
9
+ <parent >
10
+ <groupId >com.baeldung</groupId >
11
+ <artifactId >kotlin-modules</artifactId >
12
+ <version >1.0.0-SNAPSHOT</version >
13
+ </parent >
14
+
15
+ </project >
16
+
Original file line number Diff line number Diff line change
1
+ package com.baeldung.chain
2
+
3
+ import java.security.MessageDigest
4
+
5
+ data class Block (
6
+ val previousHash : String ,
7
+ val data : String ,
8
+ val timestamp : Long = System .currentTimeMillis(),
9
+ val nonce : Int = 0
10
+ ) {
11
+
12
+ val hash: String by lazy { calculateHash() }
13
+
14
+ fun calculateHash (): String {
15
+ val input = " $previousHash$data$timestamp$nonce "
16
+ return input.sha256()
17
+ }
18
+ }
19
+
20
+ fun mineBlock (previousHash : String , data : String , acceptingRegexp : Regex ): Block {
21
+ var finalBlock = Block (previousHash, data)
22
+ while (! finalBlock.hash.matches(acceptingRegexp)) {
23
+ finalBlock = finalBlock.copy(nonce = finalBlock.nonce + 1 )
24
+ }
25
+ return finalBlock
26
+ }
27
+
28
+ fun String.sha256 (): String {
29
+ val bytes = this .toByteArray()
30
+ val md = MessageDigest .getInstance(" SHA-256" )
31
+ val digest = md.digest(bytes)
32
+ return digest.fold(" " ) { str, it -> str + " %02x" .format(it) }
33
+ }
Original file line number Diff line number Diff line change
1
+ package com.baeldung.chain
2
+
3
+ class Blockchain (difficulty : Int = 5 ) {
4
+ val chain = mutableListOf<Block >()
5
+ val acceptanceRegex = " ^[0]{$difficulty }.+" .toRegex();
6
+
7
+ init {
8
+ val genesisBlock = mineBlock(" 0" , " Genesis Block" , acceptanceRegex)
9
+ chain.add(genesisBlock)
10
+ }
11
+
12
+ fun addBlock (block : Block ) {
13
+ if (isValidBlock(block)) {
14
+ chain.add(block)
15
+ } else {
16
+ throw IllegalArgumentException (" Invalid block" )
17
+ }
18
+ }
19
+
20
+ private fun isValidBlock (block : Block ): Boolean {
21
+ val lastBlock = chain.last()
22
+ return block.previousHash == lastBlock.hash &&
23
+ block.hash.matches(acceptanceRegex)
24
+ }
25
+
26
+ fun isValid (): Boolean {
27
+ if (chain.size < 2 ) return true
28
+
29
+ chain.zipWithNext().forEach { (prev, current) ->
30
+ if (current.previousHash != prev.hash) {
31
+ return false
32
+ }
33
+ }
34
+ return true
35
+ }
36
+ }
Original file line number Diff line number Diff line change
1
+ package com.baeldung.chain
2
+
3
+ fun main () {
4
+ val blockchain = Blockchain (3 )
5
+
6
+ val block1 = mineBlock(blockchain.chain.last().hash, " Block 1 Data" , blockchain.acceptanceRegex)
7
+ blockchain.addBlock(block1)
8
+
9
+ val block2 = mineBlock(blockchain.chain.last().hash, " Block 2 Data" , blockchain.acceptanceRegex)
10
+ blockchain.addBlock(block2)
11
+
12
+ val block3 = mineBlock(blockchain.chain.last().hash, " Block 3 Data" , blockchain.acceptanceRegex)
13
+ blockchain.addBlock(block3)
14
+
15
+ println (" Blockchain valid? ${blockchain.isValid()} " )
16
+
17
+ blockchain.chain.forEach {
18
+ println (" Block Data: ${it.data} , Hash: ${it.hash} " )
19
+ }
20
+ }
Original file line number Diff line number Diff line change 528
528
<module >kotlin-rsocket</module >
529
529
<module >kotlin-self-executable-jar</module >
530
530
<module >kotlin-spark</module >
531
+ <module >kotlin-blockchain</module >
531
532
<module >kotlin-testing</module >
532
533
<module >kotlin-mockito</module >
533
534
<!-- <module>kotlin-tornadofx</module> --> <!-- not compatible with Java 9+ -->
610
611
<module >kotlin-rsocket</module >
611
612
<module >kotlin-self-executable-jar</module >
612
613
<module >kotlin-spark</module >
614
+ <module >kotlin-blockchain</module >
613
615
<module >kotlin-testing</module >
614
616
<module >kotlin-mockito</module >
615
617
<!-- <module>kotlin-tornadofx</module> --> <!-- not compatible with Java 9+ -->
You can’t perform that action at this time.
0 commit comments