From 9097f1d05ae6257c1b93128c10ba4491a791f29a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 6 Aug 2025 15:39:49 +0200 Subject: [PATCH 01/40] Changed gradle version. --- build.gradle | 20 +++++++++++--------- config.json | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index 895fd6e..5abe64c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,13 @@ plugins { id 'java' - id("org.jetbrains.kotlin.jvm") version "1.9.0" - id("org.jetbrains.kotlin.plugin.serialization") version "1.9.0" + id("org.jetbrains.kotlin.jvm") version "2.2.0" + id("org.jetbrains.kotlin.plugin.serialization") version "2.2.0" } group 'nion.network' version '0.1' -configurations.implementation.setCanBeResolved(true) +//configurations.implementation.setCanBeResolved(true) repositories { mavenCentral() @@ -17,10 +17,10 @@ dependencies { testImplementation('org.junit.jupiter:junit-jupiter-api:5.8.1') testImplementation('org.junit.jupiter:junit-jupiter-engine:5.8.1') - implementation('org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0') + implementation('org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.2.0') implementation('org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.3.0') implementation('org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.0') - implementation("com.influxdb:influxdb-client-kotlin:4.0.0") + implementation("com.influxdb:influxdb-client-kotlin:7.3.0") implementation('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2-native-mt') } @@ -31,11 +31,13 @@ tasks.withType(Test).configureEach { tasks.jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE - setArchivesBaseName("Nion-Network") + manifest { attributes.put("Main-Class", "LaunchKt") } - from { - configurations.implementation.collect { it.isDirectory() ? it : zipTree(it) } - } + dependsOn(configurations.runtimeClasspath) + from({ + configurations.runtimeClasspath + .collect { it.isDirectory() ? it : zipTree(it) } + }) } \ No newline at end of file diff --git a/config.json b/config.json index 80e37ab..87b05b7 100644 --- a/config.json +++ b/config.json @@ -11,7 +11,7 @@ "influxUrl": "", "influxToken": "", "dashboardEnabled": false, - "loggingEnabled": false, + "loggingEnabled": true, "trustedLoggingEnabled": false, "historyMinuteClearance": 10, "historyCleaningFrequency": 5, diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 06febab..5c3b813 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists \ No newline at end of file From b710b769335c7fa99b967f46b9fc433806191089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 6 Aug 2025 15:45:27 +0200 Subject: [PATCH 02/40] Opted in. --- src/main/kotlin/network/data/messages/Message.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/kotlin/network/data/messages/Message.kt b/src/main/kotlin/network/data/messages/Message.kt index 30ad040..6181f04 100644 --- a/src/main/kotlin/network/data/messages/Message.kt +++ b/src/main/kotlin/network/data/messages/Message.kt @@ -1,5 +1,8 @@ +@file:OptIn(ExperimentalSerializationApi::class) + package network.data.messages +import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromByteArray import kotlinx.serialization.protobuf.ProtoBuf From 0f32d61dc67ede692944a8d6d17cabd84109098f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 6 Aug 2025 15:47:19 +0200 Subject: [PATCH 03/40] removed tests from gradle for now. --- build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 5abe64c..75a0351 100644 --- a/build.gradle +++ b/build.gradle @@ -24,10 +24,10 @@ dependencies { implementation('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2-native-mt') } -tasks.withType(Test).configureEach { - it.scanForTestClasses = false - it.useJUnitPlatform() -} +//tasks.withType(Test).configureEach { +// it.scanForTestClasses = false +// it.useJUnitPlatform() +//} tasks.jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE From 56e7e915f0f89180c0a6537376f375426cf23a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 6 Aug 2025 15:48:07 +0200 Subject: [PATCH 04/40] removed tests from gradle for now. --- build.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 75a0351..98ffe36 100644 --- a/build.gradle +++ b/build.gradle @@ -24,11 +24,11 @@ dependencies { implementation('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2-native-mt') } -//tasks.withType(Test).configureEach { -// it.scanForTestClasses = false -// it.useJUnitPlatform() -//} - +test { + useJUnitPlatform() + scanForTestClasses = false + failOnNoMatchingTests = false +} tasks.jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE From 0f4e467cb60341bce065e3ff1f84e243bf6782d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 6 Aug 2025 15:50:39 +0200 Subject: [PATCH 05/40] Build. --- build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle b/build.gradle index 98ffe36..77cd473 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,6 @@ plugins { group 'nion.network' version '0.1' - //configurations.implementation.setCanBeResolved(true) repositories { @@ -27,7 +26,6 @@ dependencies { test { useJUnitPlatform() scanForTestClasses = false - failOnNoMatchingTests = false } tasks.jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE From 3d2d574680464cbc47352357b46a9b8a946774af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 6 Aug 2025 15:54:19 +0200 Subject: [PATCH 06/40] Added jupiter. --- build.gradle | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 77cd473..d1578f1 100644 --- a/build.gradle +++ b/build.gradle @@ -13,8 +13,9 @@ repositories { } dependencies { - testImplementation('org.junit.jupiter:junit-jupiter-api:5.8.1') - testImplementation('org.junit.jupiter:junit-jupiter-engine:5.8.1') + testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.2") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.2") + implementation('org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.2.0') implementation('org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.3.0') From 19ab710aeaa52355dbb7164f9884be20c8c7aaaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 6 Aug 2025 15:55:24 +0200 Subject: [PATCH 07/40] Added jupiter. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d1578f1..a7e0873 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,7 @@ repositories { dependencies { testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.2") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.2") + testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.2") implementation('org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.2.0') From c3e1369c4c83553ab7b411e5c9a2de36db3811b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 6 Aug 2025 15:56:39 +0200 Subject: [PATCH 08/40] Added jupiter. --- build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index a7e0873..8fede9b 100644 --- a/build.gradle +++ b/build.gradle @@ -24,10 +24,10 @@ dependencies { implementation('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2-native-mt') } -test { - useJUnitPlatform() - scanForTestClasses = false -} +//test { +// useJUnitPlatform() +// scanForTestClasses = false +//} tasks.jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE From c45b63696f1f74cb4112b9ee7be3578e0053e11b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 6 Aug 2025 15:57:27 +0200 Subject: [PATCH 09/40] Solving. --- build.gradle | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 8fede9b..314098c 100644 --- a/build.gradle +++ b/build.gradle @@ -24,10 +24,11 @@ dependencies { implementation('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2-native-mt') } -//test { -// useJUnitPlatform() -// scanForTestClasses = false -//} +test { + useJUnitPlatform() + scanForTestClasses = false + failOnNoDiscoveredTests = false +} tasks.jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE From bf86880ef2fb6a7a800f3b3c64bbafb0a4fccff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 6 Aug 2025 15:58:48 +0200 Subject: [PATCH 10/40] Solving. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 314098c..37dae6a 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ dependencies { implementation('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2-native-mt') } -test { +tasks.test { useJUnitPlatform() scanForTestClasses = false failOnNoDiscoveredTests = false From 298f75a0c0e9d969691172a03228c5438a9a9973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 6 Aug 2025 17:02:57 +0200 Subject: [PATCH 11/40] Moved configuration outside of the container. Made so that the jar is built inside the container. --- Dockerfile | 20 ++++++++++++-------- Start.sh | 26 +++++++++++++------------- build.gradle | 4 ++-- config.json | 2 +- src/main/kotlin/Launch.kt | 4 ++-- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3ba93e2..807ea47 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,26 +6,30 @@ WORKDIR /root RUN apk update RUN apk add make \ bash \ - openjdk11-jre \ + openjdk21-jdk \ curl \ openssl-dev \ python3-dev \ gmp-dev -RUN apk add --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing criu-dev +RUN apk add --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing/x86_64/criu-dev RUN apk add tar -ADD *.jar Node.jar -ADD config.json config.json -ADD vdf-cli vdf-cli -ADD Start.sh Start.sh -ADD SaveContainer.sh SaveContainer.sh -ADD RunContainer.sh RunContainer.sh +COPY . . + +#ADD / +#ADD *.jar Node.jar +#ADD config.json config.json +#ADD vdf-cli vdf-cli +#ADD Start.sh Start.sh +#ADD SaveContainer.sh SaveContainer.sh +#ADD RunContainer.sh RunContainer.sh # ADD stress.sh stress.sh # COPY stress.tar stress.tar +RUN ./gradlew assemble jar RUN chmod 777 Start.sh RUN chmod 777 vdf-cli RUN mv vdf-cli /usr/bin/vdf-cli diff --git a/Start.sh b/Start.sh index 9ae8871..7b9284e 100644 --- a/Start.sh +++ b/Start.sh @@ -1,21 +1,21 @@ #!/bin/bash -if [ "$#" -ne 1 ]; then -echo "Sleeping..." -sleep $(shuf -i 1-120 -n 1) -fi +#if [ "$#" -ne 1 ]; then +#echo "Sleeping..." +#sleep $(shuf -i 1-120 -n 1) +#fi -dockerd --experimental & -while [ ! -f /var/run/docker.pid ] -do -echo "Waiting for docker daemon to initialize!" -sleep 5 -done +#dockerd --experimental & +#while [ ! -f /var/run/docker.pid ] +#do +#echo "Waiting for docker daemon to initialize!" +#sleep 5 +#done -docker load -i stress.tar +#docker load -i stress.tar if [ "$1" -eq 5005 ]; then echo "We're trusted. Running stress test." - bash stress.sh & +# bash stress.sh & fi -java -jar Node.jar $1 \ No newline at end of file +java -jar build/libs/nion-core.jar $1 $2 \ No newline at end of file diff --git a/build.gradle b/build.gradle index 37dae6a..dc288d6 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { } group 'nion.network' -version '0.1' +//version '0.1' //configurations.implementation.setCanBeResolved(true) repositories { @@ -31,7 +31,7 @@ tasks.test { } tasks.jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE - + archiveBaseName.set("nion-core") manifest { attributes.put("Main-Class", "LaunchKt") } diff --git a/config.json b/config.json index 87b05b7..f4dba90 100644 --- a/config.json +++ b/config.json @@ -21,4 +21,4 @@ "useCriu": true, "useTreeBasedMessageRoutingProtocol": true, "treeChildrenCount": 2 -} \ No newline at end of file +} diff --git a/src/main/kotlin/Launch.kt b/src/main/kotlin/Launch.kt index 258b3bf..e4e88dd 100644 --- a/src/main/kotlin/Launch.kt +++ b/src/main/kotlin/Launch.kt @@ -3,7 +3,6 @@ import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import logging.Logger import utils.tryAndReport -import java.io.File /** * Created by Mihael Valentin Berčič @@ -15,7 +14,8 @@ fun main(args: Array) { tryAndReport { System.setProperty("kotlinx.coroutines.scheduler", "off") - val configuration = Json.decodeFromString(File("./config.json").readText()) + val passedConfiguration = args.getOrNull(1) ?: throw Exception("Configuration should be passed to the docker container.") + val configuration = Json.decodeFromString(passedConfiguration) Logger.toggleLogging(configuration.loggingEnabled) args.getOrNull(0)?.toInt()?.apply { From 4d3174d7a2c11f45c2a5d910deec767f86616188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Tue, 6 Jan 2026 12:26:25 +0100 Subject: [PATCH 12/40] Fixed order of arguments to allow non-trusted ip --- Dockerfile | 2 +- Start.sh | 6 +++--- src/main/kotlin/Launch.kt | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 067fa02..d98d884 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM docker:20-dind +FROM docker:dind # RUN sed 's/http:\/\/fr\./http:\/\//' /etc/apt/sources.list WORKDIR /root diff --git a/Start.sh b/Start.sh index 7b9284e..0c556bf 100644 --- a/Start.sh +++ b/Start.sh @@ -13,9 +13,9 @@ #docker load -i stress.tar -if [ "$1" -eq 5005 ]; then - echo "We're trusted. Running stress test." +#if [ "$1" -eq 5005 ]; then +# echo "We're trusted. Running stress test." # bash stress.sh & -fi +#fi java -jar build/libs/nion-core.jar $1 $2 \ No newline at end of file diff --git a/src/main/kotlin/Launch.kt b/src/main/kotlin/Launch.kt index 82c1686..2ca9ed0 100644 --- a/src/main/kotlin/Launch.kt +++ b/src/main/kotlin/Launch.kt @@ -3,6 +3,7 @@ import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import logging.Logger import utils.tryAndReport +import java.io.File /** * Created by Mihael Valentin Berčič @@ -14,11 +15,10 @@ fun main(args: Array) { tryAndReport { System.setProperty("kotlinx.coroutines.scheduler", "off") - val passedConfiguration = args.getOrNull(1) ?: throw Exception("Configuration should be passed to the docker container.") + val passedConfiguration = args.getOrNull(0) ?: throw Exception("Configuration should be passed to the docker container.") val configuration = Json.decodeFromString(passedConfiguration) - Logger.toggleLogging(configuration.loggingEnabled) - args.getOrNull(0)?.toInt()?.apply { + args.getOrNull(1)?.toInt()?.apply { configuration.port = this } Nion(configuration).apply { From 02421d3070b19f9f6a552b50434fa8c965468cf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Tue, 6 Jan 2026 12:56:19 +0100 Subject: [PATCH 13/40] Fixed dockerfile. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d98d884..2db0ebc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,6 +32,6 @@ COPY . . RUN ./gradlew assemble jar RUN chmod 777 Start.sh RUN chmod 777 vdf-cli -RUN mv vdf-cli /usr/bin/vdf-cli +# RUN mv vdf-cli /usr/bin/vdf-cli RUN chmod +x Start.sh ENTRYPOINT ["./Start.sh"] \ No newline at end of file From dc1d73819c18efc60c80867dff5da09e22b6120f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Tue, 6 Jan 2026 13:06:31 +0100 Subject: [PATCH 14/40] Fixed dockerfile. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2db0ebc..68b5a81 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ RUN apk add --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing/x86_6 RUN apk add tar COPY . . - +ADD vdf-cli vdf-cli #ADD / #ADD *.jar Node.jar #ADD config.json config.json From d875eb2222bf0588707b0d6d4f57f5c4c652ef39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 7 Jan 2026 10:56:58 +0100 Subject: [PATCH 15/40] Issues with vdf-cli --- src/main/kotlin/chain/VerifiableDelay.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/chain/VerifiableDelay.kt b/src/main/kotlin/chain/VerifiableDelay.kt index 891171d..8d7142c 100644 --- a/src/main/kotlin/chain/VerifiableDelay.kt +++ b/src/main/kotlin/chain/VerifiableDelay.kt @@ -11,6 +11,7 @@ class VerifiableDelay { /** Runs a vdf-cli command and returns the output of vdf computation. */ fun computeProof(difficulty: Int, hash: ByteArray): String { + return "0000" // Issues with computing vdf-cli val hexHash = hash.asHex val needed = hexHash.length % 2 val processBuilder = ProcessBuilder() From 7cbe1c72eba32e4ddd2dae86d8d88030f895f17e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Fri, 9 Jan 2026 12:09:27 +0100 Subject: [PATCH 16/40] Added block storage. --- build.gradle | 4 ++++ src/main/kotlin/Nion.kt | 2 ++ src/main/kotlin/chain/Chain.kt | 18 ++++++++++++++++++ src/main/kotlin/database/Tables.kt | 18 ++++++++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 src/main/kotlin/database/Tables.kt diff --git a/build.gradle b/build.gradle index 11f444f..18a5cb2 100644 --- a/build.gradle +++ b/build.gradle @@ -24,6 +24,10 @@ dependencies { implementation('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2-native-mt') implementation("io.javalin:javalin:5.6.1") implementation("org.slf4j:slf4j-simple:2.0.7") + + implementation("org.jetbrains.exposed:exposed-core:1.0.0-rc-3") + implementation("org.jetbrains.exposed:exposed-jdbc:1.0.0-rc-3") + implementation("org.jetbrains.exposed:exposed-dao:1.0.0-rc-3") } tasks.test { diff --git a/src/main/kotlin/Nion.kt b/src/main/kotlin/Nion.kt index 9d5e83b..326a527 100644 --- a/src/main/kotlin/Nion.kt +++ b/src/main/kotlin/Nion.kt @@ -5,6 +5,7 @@ import logging.Logger import network.data.Endpoint import network.data.MessageProcessing import network.data.messages.Message +import org.jetbrains.exposed.v1.jdbc.Database import utils.asHex import utils.launchCoroutine import utils.runAfter @@ -48,6 +49,7 @@ class Nion(configuration: Configuration) : ChainBuilder(configuration) { Dashboard.reportException(Exception("Local address: $localAddress!")) return } + Database.connect("jdbc:sqlite:nion.db", "org.sqlite.JDBC") attemptBootstrap() attemptInclusion() } diff --git a/src/main/kotlin/chain/Chain.kt b/src/main/kotlin/chain/Chain.kt index 2dc9433..0c08611 100644 --- a/src/main/kotlin/chain/Chain.kt +++ b/src/main/kotlin/chain/Chain.kt @@ -1,7 +1,10 @@ package chain import chain.data.Block +import database.BlockTable import logging.Logger +import org.jetbrains.exposed.v1.jdbc.insert +import org.jetbrains.exposed.v1.jdbc.transactions.transaction import utils.CircularList import utils.asHex import utils.tryWithLock @@ -47,7 +50,22 @@ class Chain(private val verifiableDelay: VerifiableDelay, private val initialDif lock.tryWithLock { blocks.add(nextBlock) // ToDo: Put chain history in some sort of storage instead of keeping in memory. + transaction { + BlockTable.insert { + it[BlockTable.slot] = nextBlock.slot + it[BlockTable.difficulty] = nextBlock.difficulty + it[BlockTable.blockProducer] = nextBlock.blockProducer + it[BlockTable.timestamp] = nextBlock.timestamp + it[BlockTable.precedentHash] = nextBlock.precedentHash.toHexString() + it[BlockTable.votes] = nextBlock.votes + it[BlockTable.committee] = nextBlock.committee.joinToString() + it[BlockTable.hash] = nextBlock.hash.toHexString() + it[BlockTable.votedMembers] = nextBlock.votedMembers.joinToString() + + } + } } + Logger.chain("Block[${nextBlock.votes}/$committeeSize] added [${nextBlock.slot}].") } return true diff --git a/src/main/kotlin/database/Tables.kt b/src/main/kotlin/database/Tables.kt new file mode 100644 index 0000000..7f89997 --- /dev/null +++ b/src/main/kotlin/database/Tables.kt @@ -0,0 +1,18 @@ +package database + +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable + +/** + * @author Mihael Berčič on 9. 1. 26. + */ +object BlockTable : IntIdTable("blocks") { + val slot = long("slot") + val difficulty = integer("difficulty").default(0) + val blockProducer = text("block_producer") + val timestamp = long("timestamp") + val precedentHash = varchar("precendtHash", 255) + val votes = integer("votes").default(0) + val committee = text("committee") + val hash = text("hash") + val votedMembers = text("voted_members") +} \ No newline at end of file From 5c422e0cbcd9fd17728e93ecf6cf2dc8135425fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Fri, 9 Jan 2026 12:15:00 +0100 Subject: [PATCH 17/40] Added the sqlite jdbc --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 18a5cb2..afe79ec 100644 --- a/build.gradle +++ b/build.gradle @@ -28,6 +28,7 @@ dependencies { implementation("org.jetbrains.exposed:exposed-core:1.0.0-rc-3") implementation("org.jetbrains.exposed:exposed-jdbc:1.0.0-rc-3") implementation("org.jetbrains.exposed:exposed-dao:1.0.0-rc-3") + implementation("org.xerial:sqlite-jdbc:3.49.1.0") } tasks.test { From faeb03d1389e46b23466e1bbba127b5b038fd151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Fri, 9 Jan 2026 12:19:46 +0100 Subject: [PATCH 18/40] Addd table creation. --- src/main/kotlin/Nion.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/kotlin/Nion.kt b/src/main/kotlin/Nion.kt index 326a527..2aae9f4 100644 --- a/src/main/kotlin/Nion.kt +++ b/src/main/kotlin/Nion.kt @@ -1,4 +1,5 @@ import chain.ChainBuilder +import database.BlockTable import kotlinx.serialization.ExperimentalSerializationApi import logging.Dashboard import logging.Logger @@ -6,6 +7,8 @@ import network.data.Endpoint import network.data.MessageProcessing import network.data.messages.Message import org.jetbrains.exposed.v1.jdbc.Database +import org.jetbrains.exposed.v1.jdbc.SchemaUtils +import org.jetbrains.exposed.v1.jdbc.transactions.transaction import utils.asHex import utils.launchCoroutine import utils.runAfter @@ -50,6 +53,9 @@ class Nion(configuration: Configuration) : ChainBuilder(configuration) { return } Database.connect("jdbc:sqlite:nion.db", "org.sqlite.JDBC") + transaction { + SchemaUtils.create(BlockTable) + } attemptBootstrap() attemptInclusion() } From ca9c86f395ecbac14abc01f82377fbf77be55517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Mon, 12 Jan 2026 16:46:46 +0100 Subject: [PATCH 19/40] Looking for websocket issues. --- src/main/kotlin/chain/Chain.kt | 10 +++++-- src/main/kotlin/network/messaging/Server.kt | 32 +++++++++++++++++---- src/main/kotlin/network/rpc/RPCManager.kt | 1 + 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/chain/Chain.kt b/src/main/kotlin/chain/Chain.kt index 0c08611..d7e673b 100644 --- a/src/main/kotlin/chain/Chain.kt +++ b/src/main/kotlin/chain/Chain.kt @@ -16,7 +16,11 @@ import kotlin.concurrent.withLock * on 16/11/2021 at 16:21 * using IntelliJ IDEA */ -class Chain(private val verifiableDelay: VerifiableDelay, private val initialDifficulty: Int, private val committeeSize: Int) { +class Chain( + private val verifiableDelay: VerifiableDelay, + private val initialDifficulty: Int, + private val committeeSize: Int +) { private val lock = ReentrantLock(true) private val blocks = CircularList(50) // ToDo: Remove, do not use Circular List but use persistent storage! @@ -37,7 +41,8 @@ class Chain(private val verifiableDelay: VerifiableDelay, private val initialDif val lastBlock = getLastBlock() val lastHash = lastBlock?.hash ?: "FFFF".toByteArray() val difficulty = lastBlock?.difficulty ?: initialDifficulty - val isLegitimate = nextBlock.slot == (lastBlock?.slot ?: 0) + 1 // verifiableDelay.verifyProof(lastHash, difficulty, nextBlock.vdfProof) + val isLegitimate = nextBlock.slot == (lastBlock?.slot + ?: 0) + 1 // verifiableDelay.verifyProof(lastHash, difficulty, nextBlock.vdfProof) if (!isLegitimate) { Logger.trace("Proof is not legitimate for block ${nextBlock.slot}!") Logger.chain("Last hash: ${lastHash.asHex}") @@ -48,6 +53,7 @@ class Chain(private val verifiableDelay: VerifiableDelay, private val initialDif return false } lock.tryWithLock { + blocks.add(nextBlock) // ToDo: Put chain history in some sort of storage instead of keeping in memory. transaction { diff --git a/src/main/kotlin/network/messaging/Server.kt b/src/main/kotlin/network/messaging/Server.kt index 635adf3..02eabff 100644 --- a/src/main/kotlin/network/messaging/Server.kt +++ b/src/main/kotlin/network/messaging/Server.kt @@ -65,6 +65,7 @@ abstract class Server(val configuration: Configuration) : RPCManager(configurati Logger.trace("Clearing message history...") messageHistory.entries.removeIf { (_, value) -> currentTime - value > maximumAge } } + } abstract fun processMessage(message: Message) @@ -91,7 +92,10 @@ abstract class Server(val configuration: Configuration) : RPCManager(configurati /** Returns [Configuration.broadcastSpreadPercentage] number of nodes. */ fun pickRandomNodes(amount: Int = 0): List { - val toTake = if (amount > 0) amount else 5 + (configuration.broadcastSpreadPercentage * Integer.max(totalKnownNodes, 1) / 100) + val toTake = if (amount > 0) amount else 5 + (configuration.broadcastSpreadPercentage * Integer.max( + totalKnownNodes, + 1 + ) / 100) return getRandomNodes(toTake).filter { it.identifier != localNode.identifier } } @@ -160,7 +164,11 @@ abstract class Server(val configuration: Configuration) : RPCManager(configurati val message = ProtoBuf.decodeFromByteArray(data) if (alreadySeen(message.uid.asHex)) return@use processingQueue.add(message) - if (message.endpoint.transmissionType == TransmissionType.Broadcast) broadcast(TransmissionLayer.TCP, message.uid.asHex, data) + if (message.endpoint.transmissionType == TransmissionType.Broadcast) broadcast( + TransmissionLayer.TCP, + message.uid.asHex, + data + ) } } } @@ -199,14 +207,21 @@ abstract class Server(val configuration: Configuration) : RPCManager(configurati broadcastNodes.add(neighbour) broadcastNodes.addAll(childrenKeys) broadcastNodes.addAll(neighbourChildrenKeys) - Logger.error("[$index] [$children] Neighbour: $neighbourIndex ... Children: ${childrenKeys.joinToString(",") { "${shuffled.indexOf(it)}" }}") + Logger.error( + "[$index] [$children] Neighbour: $neighbourIndex ... Children: ${ + childrenKeys.joinToString( + "," + ) { "${shuffled.indexOf(it)}" } + }" + ) } else -> broadcastNodes.addAll(pickRandomNodes().map { it.publicKey }) } - val knownAndNotInSet = knownNodes.values.map(Node::publicKey).filter { !validatorSet.activeValidators.contains(it) } + val knownAndNotInSet = + knownNodes.values.map(Node::publicKey).filter { !validatorSet.activeValidators.contains(it) } broadcastNodes.addAll(knownAndNotInSet) Logger.trace("We have to retransmit to [total: ${shuffled.size}] --> ${broadcastNodes.size} nodes.") @@ -214,7 +229,8 @@ abstract class Server(val configuration: Configuration) : RPCManager(configurati broadcastNodes.forEach { publicKey -> query(publicKey) { val outgoingData = OutgoingData(it, *data) - val outgoingQueue = if (transmissionLayer == TransmissionLayer.UDP) udpOutgoingQueue else tcpOutgoingQueue + val outgoingQueue = + if (transmissionLayer == TransmissionLayer.UDP) udpOutgoingQueue else tcpOutgoingQueue outgoingQueue.add(outgoingData) } } @@ -242,7 +258,11 @@ abstract class Server(val configuration: Configuration) : RPCManager(configurati if (alreadySeen(packetId) || alreadySeen(messageId)) return@tryAndReport val endpoint = Endpoint.byId(inputStream.read().toByte()) ?: return@tryAndReport - if (endpoint.transmissionType == TransmissionType.Broadcast) broadcast(TransmissionLayer.UDP, messageId, packet.data.copyOf()) + if (endpoint.transmissionType == TransmissionType.Broadcast) broadcast( + TransmissionLayer.UDP, + messageId, + packet.data.copyOf() + ) val totalSlices = inputStream.readInt() val currentSlice = inputStream.readInt() diff --git a/src/main/kotlin/network/rpc/RPCManager.kt b/src/main/kotlin/network/rpc/RPCManager.kt index 30b1dea..a4d92ac 100644 --- a/src/main/kotlin/network/rpc/RPCManager.kt +++ b/src/main/kotlin/network/rpc/RPCManager.kt @@ -77,6 +77,7 @@ open class RPCManager(configuration: Configuration) : Kademlia(configuration) { val serialisedData = Json.encodeToString(message) val clientList = subscribedClients[topic] ?: return clientList.forEach { + println("Websocket data: $serialisedData") try { it.send(serialisedData) } catch (e: Exception) { From 43de0243f9aa88ce1b7164c90132ab94e43fc5ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Mon, 12 Jan 2026 17:09:52 +0100 Subject: [PATCH 20/40] Fixed ws. --- src/main/kotlin/network/rpc/RPCManager.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/network/rpc/RPCManager.kt b/src/main/kotlin/network/rpc/RPCManager.kt index a4d92ac..30b1dea 100644 --- a/src/main/kotlin/network/rpc/RPCManager.kt +++ b/src/main/kotlin/network/rpc/RPCManager.kt @@ -77,7 +77,6 @@ open class RPCManager(configuration: Configuration) : Kademlia(configuration) { val serialisedData = Json.encodeToString(message) val clientList = subscribedClients[topic] ?: return clientList.forEach { - println("Websocket data: $serialisedData") try { it.send(serialisedData) } catch (e: Exception) { From debd45b12fb59c17b69beac9e82fec278af0a4be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Tue, 13 Jan 2026 14:36:40 +0100 Subject: [PATCH 21/40] Added stress test. --- Start.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Start.sh b/Start.sh index 0c556bf..16f7a19 100644 --- a/Start.sh +++ b/Start.sh @@ -4,12 +4,12 @@ #sleep $(shuf -i 1-120 -n 1) #fi -#dockerd --experimental & -#while [ ! -f /var/run/docker.pid ] -#do -#echo "Waiting for docker daemon to initialize!" -#sleep 5 -#done +dockerd --experimental & +while [ ! -f /var/run/docker.pid ] +do +echo "Waiting for docker daemon to initialize!" +sleep 5 +done #docker load -i stress.tar From 803127692ead8640891771e9b587a4df239ec899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 11:12:28 +0100 Subject: [PATCH 22/40] Added reading stats. --- src/main/kotlin/docker/DockerContainer.kt | 25 +++++++++++- src/main/kotlin/docker/DockerProxy.kt | 48 ++--------------------- 2 files changed, 27 insertions(+), 46 deletions(-) diff --git a/src/main/kotlin/docker/DockerContainer.kt b/src/main/kotlin/docker/DockerContainer.kt index 4748742..9b29f86 100644 --- a/src/main/kotlin/docker/DockerContainer.kt +++ b/src/main/kotlin/docker/DockerContainer.kt @@ -1,5 +1,6 @@ package docker +import com.google.gson.annotations.SerializedName import kotlinx.serialization.Serializable import utils.CircularList @@ -27,4 +28,26 @@ data class DockerContainer( ) { val averageCpuUsage get(): Double = cpuUsage.elements().average().takeIf { !it.isNaN() } ?: 0.0 val averageMemoryUsage get(): Double = memoryUsage.elements().average().takeIf { !it.isNaN() } ?: 0.0 -} \ No newline at end of file +} + +@Serializable +data class DockerStatsModel( + @SerializedName("BlockIO") + val blockIo: String, + @SerializedName("CPUPerc") + val cpuperc: String, + @SerializedName("Container") + val container: String, + @SerializedName("ID") + val id: String, + @SerializedName("MemPerc") + val memPerc: String, + @SerializedName("MemUsage") + val memUsage: String, + @SerializedName("Name") + val name: String, + @SerializedName("NetIO") + val netIo: String, + @SerializedName("PIDs") + val pids: String, +) diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index 7a8fb16..6d8f58d 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -8,10 +8,7 @@ import logging.Logger import network.data.Endpoint import network.data.clusters.Cluster import network.data.messages.Message -import utils.CircularList import utils.runAfter -import java.nio.ByteBuffer -import java.util.* import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.withLock @@ -94,50 +91,11 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con val numberOfElements = (configuration.slotDuration / 1000).toInt() val process = ProcessBuilder() - .command("docker", "stats", "--no-trunc", "--format", "{{.ID}} {{.CPUPerc}} {{.MemPerc}} {{.PIDs}}") + .command("docker", "stats", "--no-stream", "--no-trunc", "--format", "{{ json . }}") .redirectErrorStream(true) .start() - - val buffer = ByteBuffer.allocate(100_000) - val escapeSequence = byteArrayOf(0x1B, 0x5B, 0x32, 0x4A, 0x1B, 0x5B, 0x48) // Escape sequence of CLI output. - var escapeIndex = 0 - process.inputStream.use { inputStream -> - while (true) { - try { - val byte = inputStream.read().toByte() - if (byte < 0) break - buffer.put(byte) - if (byte == escapeSequence[escapeIndex]) escapeIndex++ else escapeIndex = 0 - if (escapeIndex != escapeSequence.size) continue // If escape sequence was not detected, continue reading data. - val length = buffer.position() - escapeSequence.size - if (length > 0) String(buffer.array(), 0, length).split("\n").map { line -> - if (line.isNotEmpty()) { - val fields = line.split(" ") - val containerId = fields[0] - if (fields.none { it.contains("-") || it.isEmpty() }) { - val cpuPercentage = fields[1].trim('%').toDouble() - val memoryPercentage = fields[2].trim('%').toDouble() - val activeProcesses = fields[3].toInt() - val container = localContainers.computeIfAbsent(containerId) { - DockerContainer(containerId, activeProcesses, CircularList(numberOfElements), CircularList(numberOfElements)) - } - container.apply { - cpuUsage.add(cpuPercentage) - memoryUsage.add(memoryPercentage) - updated = System.currentTimeMillis() - processes = activeProcesses - } - } else localContainers[containerId]?.updated = System.currentTimeMillis() - } - } - buffer.clear() - escapeIndex = 0 - } catch (e: Exception) { - buffer.clear() - escapeIndex = 0 - Dashboard.reportException(e) - } - } + process.inputReader().readLines().forEach { line -> + println("Read line from docker stats: $line") } } From f2a319894ed3d33ab559a565c01c1d08d1fcba02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 11:20:52 +0100 Subject: [PATCH 23/40] Adding parsing. --- src/main/kotlin/docker/DockerProxy.kt | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index 6d8f58d..95b100a 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -94,9 +94,28 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con .command("docker", "stats", "--no-stream", "--no-trunc", "--format", "{{ json . }}") .redirectErrorStream(true) .start() - process.inputReader().readLines().forEach { line -> - println("Read line from docker stats: $line") + + println("Reading docker stats") + val reader = process.inputStream.bufferedReader() + println("Reader $reader") + reader.use { + it.readAllLines().forEach { line -> + println(line) + } + } + println("Done reading") + + /* + val container = localContainers.computeIfAbsent(containerId) { + DockerContainer(containerId, activeProcesses, CircularList(numberOfElements), CircularList(numberOfElements)) + } + container.apply { + cpuUsage.add(cpuPercentage) + memoryUsage.add(memoryPercentage) + updated = System.currentTimeMillis() + processes = activeProcesses } + */ } } \ No newline at end of file From 03ffbcad217e18fc6d6ab238e4f34ef6f04c49b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 11:25:05 +0100 Subject: [PATCH 24/40] Looking for issues with buffering. --- src/main/kotlin/docker/DockerProxy.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index 95b100a..34f10ee 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -98,10 +98,8 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con println("Reading docker stats") val reader = process.inputStream.bufferedReader() println("Reader $reader") - reader.use { - it.readAllLines().forEach { line -> - println(line) - } + reader.readLines().forEach { line -> + println(line) } println("Done reading") From fe82851ef3d392f78ea0f31a766766d5312b1257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 11:36:19 +0100 Subject: [PATCH 25/40] Looking for issues with buffering. --- src/main/kotlin/docker/DockerProxy.kt | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index 34f10ee..4dfcb2b 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -88,20 +88,25 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con /** Starts a process of `docker stats` and keeps the [localStatistics] up to date. */ private fun listenForDockerStatistics() { + println("Started a docker stats process") val numberOfElements = (configuration.slotDuration / 1000).toInt() - val process = ProcessBuilder() - .command("docker", "stats", "--no-stream", "--no-trunc", "--format", "{{ json . }}") - .redirectErrorStream(true) - .start() + while (true) { + val process = ProcessBuilder() + .command("docker", "stats", "--no-stream", "--no-trunc", "--format", "{{ json . }}") + .redirectErrorStream(true) + .start() - println("Reading docker stats") - val reader = process.inputStream.bufferedReader() - println("Reader $reader") - reader.readLines().forEach { line -> - println(line) + println("Reading docker stats") + val reader = process.inputStream.bufferedReader() + println("Reader $reader") + reader.readLines().forEach { line -> + println(line) + } + println("Done reading") + Thread.sleep(5000) } - println("Done reading") + /* val container = localContainers.computeIfAbsent(containerId) { From f34ed4bff578428ab60b8fba446d3e5f1ee4cf7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 12:12:05 +0100 Subject: [PATCH 26/40] Looking for issues with buffering. --- src/main/kotlin/docker/DockerContainer.kt | 4 +- src/main/kotlin/docker/DockerProxy.kt | 46 ++++++++++++----------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/main/kotlin/docker/DockerContainer.kt b/src/main/kotlin/docker/DockerContainer.kt index 9b29f86..36b32b7 100644 --- a/src/main/kotlin/docker/DockerContainer.kt +++ b/src/main/kotlin/docker/DockerContainer.kt @@ -35,13 +35,13 @@ data class DockerStatsModel( @SerializedName("BlockIO") val blockIo: String, @SerializedName("CPUPerc") - val cpuperc: String, + val cpuPercentage: String, @SerializedName("Container") val container: String, @SerializedName("ID") val id: String, @SerializedName("MemPerc") - val memPerc: String, + val memoryPercentage: String, @SerializedName("MemUsage") val memUsage: String, @SerializedName("Name") diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index 4dfcb2b..36d5218 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -3,11 +3,14 @@ package docker import Configuration import chain.data.Block import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json import logging.Dashboard import logging.Logger import network.data.Endpoint import network.data.clusters.Cluster import network.data.messages.Message +import utils.CircularList import utils.runAfter import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.locks.ReentrantLock @@ -90,34 +93,33 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con private fun listenForDockerStatistics() { println("Started a docker stats process") val numberOfElements = (configuration.slotDuration / 1000).toInt() - + val process = ProcessBuilder() + .command("docker", "stats", "--no-stream", "--no-trunc", "--format", "{{ json . }}") + .redirectErrorStream(true) + .start() + val reader = process.inputStream.bufferedReader() while (true) { - val process = ProcessBuilder() - .command("docker", "stats", "--no-stream", "--no-trunc", "--format", "{{ json . }}") - .redirectErrorStream(true) - .start() - - println("Reading docker stats") - val reader = process.inputStream.bufferedReader() - println("Reader $reader") - reader.readLines().forEach { line -> - println(line) + val line = reader.readLine() + println("Line read: $line") + val stats = Json.decodeFromString(line) + val pids = stats.pids.toIntOrNull() ?: 0 + val cpuPercentage = stats.cpuPercentage.replace("%", "").toDoubleOrNull() ?: 0.0 + val memoryPercentage = stats.memoryPercentage.replace("%", "").toDoubleOrNull() ?: 0.0 + + val container = localContainers.computeIfAbsent(stats.id) { + DockerContainer(stats.id, pids, CircularList(numberOfElements), CircularList(numberOfElements)) + } + container.apply { + cpuUsage.add(cpuPercentage) + memoryUsage.add(memoryPercentage) + processes = pids + updated = System.currentTimeMillis() } - println("Done reading") - Thread.sleep(5000) } /* - val container = localContainers.computeIfAbsent(containerId) { - DockerContainer(containerId, activeProcesses, CircularList(numberOfElements), CircularList(numberOfElements)) - } - container.apply { - cpuUsage.add(cpuPercentage) - memoryUsage.add(memoryPercentage) - updated = System.currentTimeMillis() - processes = activeProcesses - } + */ } From 54096959a691b2b2fd0cb93acc19b5bc27557197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 12:17:30 +0100 Subject: [PATCH 27/40] Looking for issues with buffering. --- src/main/kotlin/docker/DockerProxy.kt | 2 +- stress.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index 36d5218..26cceca 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -94,7 +94,7 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con println("Started a docker stats process") val numberOfElements = (configuration.slotDuration / 1000).toInt() val process = ProcessBuilder() - .command("docker", "stats", "--no-stream", "--no-trunc", "--format", "{{ json . }}") + .command("docker", "stats", "--no-trunc", "--format", "{{ json . }}") .redirectErrorStream(true) .start() val reader = process.inputStream.bufferedReader() diff --git a/stress.sh b/stress.sh index f1c0092..b32e321 100644 --- a/stress.sh +++ b/stress.sh @@ -1,5 +1,5 @@ #!/bin/bash -count=200 +count=$1 echo "Running stress test of $count apps..." for i in $(seq $count); do From a44e0c938083d0c740fb6a7e7d2ccc64958605d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 12:23:00 +0100 Subject: [PATCH 28/40] Looking for issues with buffering. --- src/main/kotlin/docker/DockerProxy.kt | 43 ++++++++++++++------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index 26cceca..ecc1ce8 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -93,27 +93,30 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con private fun listenForDockerStatistics() { println("Started a docker stats process") val numberOfElements = (configuration.slotDuration / 1000).toInt() - val process = ProcessBuilder() - .command("docker", "stats", "--no-trunc", "--format", "{{ json . }}") - .redirectErrorStream(true) - .start() - val reader = process.inputStream.bufferedReader() + while (true) { - val line = reader.readLine() - println("Line read: $line") - val stats = Json.decodeFromString(line) - val pids = stats.pids.toIntOrNull() ?: 0 - val cpuPercentage = stats.cpuPercentage.replace("%", "").toDoubleOrNull() ?: 0.0 - val memoryPercentage = stats.memoryPercentage.replace("%", "").toDoubleOrNull() ?: 0.0 - - val container = localContainers.computeIfAbsent(stats.id) { - DockerContainer(stats.id, pids, CircularList(numberOfElements), CircularList(numberOfElements)) - } - container.apply { - cpuUsage.add(cpuPercentage) - memoryUsage.add(memoryPercentage) - processes = pids - updated = System.currentTimeMillis() + // TODO: I believe this could be optimised + val process = ProcessBuilder() + .command("docker", "stats", "--no-trunc", "--format", "{{ json . }}") + .redirectErrorStream(true) + .start() + val reader = process.inputStream.bufferedReader() + + reader.readLines().forEach { line -> + val stats = Json.decodeFromString(line) + val pids = stats.pids.toIntOrNull() ?: 0 + val cpuPercentage = stats.cpuPercentage.replace("%", "").toDoubleOrNull() ?: 0.0 + val memoryPercentage = stats.memoryPercentage.replace("%", "").toDoubleOrNull() ?: 0.0 + + val container = localContainers.computeIfAbsent(stats.id) { + DockerContainer(stats.id, pids, CircularList(numberOfElements), CircularList(numberOfElements)) + } + container.apply { + cpuUsage.add(cpuPercentage) + memoryUsage.add(memoryPercentage) + processes = pids + updated = System.currentTimeMillis() + } } } From 3a4e633868bd924950783c388f5c310c93b3cccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 12:25:16 +0100 Subject: [PATCH 29/40] Looking for issues with buffering. --- src/main/kotlin/docker/DockerProxy.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index ecc1ce8..0bba723 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -105,8 +105,8 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con reader.readLines().forEach { line -> val stats = Json.decodeFromString(line) val pids = stats.pids.toIntOrNull() ?: 0 - val cpuPercentage = stats.cpuPercentage.replace("%", "").toDoubleOrNull() ?: 0.0 - val memoryPercentage = stats.memoryPercentage.replace("%", "").toDoubleOrNull() ?: 0.0 + val cpuPercentage = stats.cpuPercentage.trim('%').toDoubleOrNull() ?: 0.0 + val memoryPercentage = stats.memoryPercentage.trim('%').toDoubleOrNull() ?: 0.0 val container = localContainers.computeIfAbsent(stats.id) { DockerContainer(stats.id, pids, CircularList(numberOfElements), CircularList(numberOfElements)) From aeabd59d86f708a7b883fdb580467eac2920c654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 12:27:22 +0100 Subject: [PATCH 30/40] Looking for issues with buffering. --- src/main/kotlin/docker/DockerProxy.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index 0bba723..b771432 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -97,7 +97,7 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con while (true) { // TODO: I believe this could be optimised val process = ProcessBuilder() - .command("docker", "stats", "--no-trunc", "--format", "{{ json . }}") + .command("docker", "stats", "--no-stream", "--no-trunc", "--format", "{{ json . }}") .redirectErrorStream(true) .start() val reader = process.inputStream.bufferedReader() @@ -118,6 +118,7 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con updated = System.currentTimeMillis() } } + Thread.sleep(5000) } From edccd1cc2971d5ac0f7a3f46a57775fb90533f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 12:31:11 +0100 Subject: [PATCH 31/40] Looking for issues with buffering. --- src/main/kotlin/docker/DockerProxy.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index b771432..46dd3b8 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -93,7 +93,7 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con private fun listenForDockerStatistics() { println("Started a docker stats process") val numberOfElements = (configuration.slotDuration / 1000).toInt() - + val json = Json { ignoreUnknownKeys = true } while (true) { // TODO: I believe this could be optimised val process = ProcessBuilder() @@ -103,7 +103,7 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con val reader = process.inputStream.bufferedReader() reader.readLines().forEach { line -> - val stats = Json.decodeFromString(line) + val stats = json.decodeFromString(line) val pids = stats.pids.toIntOrNull() ?: 0 val cpuPercentage = stats.cpuPercentage.trim('%').toDoubleOrNull() ?: 0.0 val memoryPercentage = stats.memoryPercentage.trim('%').toDoubleOrNull() ?: 0.0 From 2a390e803d0a0e8b2a7253e76c8c998dd28de89d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 12:45:36 +0100 Subject: [PATCH 32/40] Looking for issues with buffering. --- src/main/kotlin/docker/DockerProxy.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index 46dd3b8..e043c3d 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -93,7 +93,9 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con private fun listenForDockerStatistics() { println("Started a docker stats process") val numberOfElements = (configuration.slotDuration / 1000).toInt() - val json = Json { ignoreUnknownKeys = true } + val json = Json { + ignoreUnknownKeys = true + } while (true) { // TODO: I believe this could be optimised val process = ProcessBuilder() @@ -103,6 +105,7 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con val reader = process.inputStream.bufferedReader() reader.readLines().forEach { line -> + println(line) val stats = json.decodeFromString(line) val pids = stats.pids.toIntOrNull() ?: 0 val cpuPercentage = stats.cpuPercentage.trim('%').toDoubleOrNull() ?: 0.0 From 20ca1acd5ef4ecd9042b1e0c4193d1ec76a310ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 13:26:16 +0100 Subject: [PATCH 33/40] Looking for issues with buffering. --- src/main/kotlin/docker/DockerContainer.kt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/docker/DockerContainer.kt b/src/main/kotlin/docker/DockerContainer.kt index 36b32b7..c17ef08 100644 --- a/src/main/kotlin/docker/DockerContainer.kt +++ b/src/main/kotlin/docker/DockerContainer.kt @@ -1,6 +1,7 @@ package docker import com.google.gson.annotations.SerializedName +import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import utils.CircularList @@ -32,22 +33,22 @@ data class DockerContainer( @Serializable data class DockerStatsModel( - @SerializedName("BlockIO") + @SerialName("BlockIO") val blockIo: String, - @SerializedName("CPUPerc") + @SerialName("CPUPerc") val cpuPercentage: String, - @SerializedName("Container") + @SerialName("Container") val container: String, - @SerializedName("ID") + @SerialName("ID") val id: String, - @SerializedName("MemPerc") + @SerialName("MemPerc") val memoryPercentage: String, - @SerializedName("MemUsage") + @SerialName("MemUsage") val memUsage: String, - @SerializedName("Name") + @SerialName("Name") val name: String, - @SerializedName("NetIO") + @SerialName("NetIO") val netIo: String, - @SerializedName("PIDs") + @SerialName("PIDs") val pids: String, ) From 9bb8dad2c4b3d3a8566f9e80a3ed00065c969df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 13:31:22 +0100 Subject: [PATCH 34/40] Looking for issues with buffering. --- src/main/kotlin/docker/DockerProxy.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index e043c3d..708da3e 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -65,7 +65,8 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con fun sendDockerStatistics(block: Block, blockProducer: String, clusters: Map>) { val slot = block.slot val currentTime = System.currentTimeMillis() - localContainers.entries.removeIf { (_, container) -> currentTime - container.updated >= 1000 } + println("Containers length before remove: ${localContainers.size}") + localContainers.entries.removeIf { (_, container) -> currentTime - container.updated >= 30_000 } val mapped: List = localContainers.values.map { it.copy(id = networkMappings[it.id] ?: it.id) } val localStatistics = DockerStatistics(localNode.publicKey, mapped, slot) From 59bcc2b780ec53ba7964f8808da3f62825088c15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 13:56:34 +0100 Subject: [PATCH 35/40] Added serialisation to circular lists --- src/main/kotlin/utils/CircularList.kt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/utils/CircularList.kt b/src/main/kotlin/utils/CircularList.kt index 89a8ece..27401df 100644 --- a/src/main/kotlin/utils/CircularList.kt +++ b/src/main/kotlin/utils/CircularList.kt @@ -8,15 +8,12 @@ import kotlinx.serialization.Serializable * using IntelliJ IDEA */ @Serializable -class CircularList(private val maxCapacity: Int) : ArrayList(maxCapacity) { +class CircularList(private val maxCapacity: Int, val items: ArrayList = ArrayList(maxCapacity)) { /** Adds a new element to the list and removes the oldest element.*/ - override fun add(element: T): Boolean { - if (size == maxCapacity) removeFirst() - return super.add(element) + fun add(element: T): Boolean { + if (items.size == maxCapacity) items.removeFirst() + return items.add(element) } - /** Returns all elements in this circular list. */ - fun elements() = toList() - } \ No newline at end of file From aaceeb3646648f94227e155f40130cfc52b5be46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 14:12:05 +0100 Subject: [PATCH 36/40] Added serialisation to circular lists --- src/main/kotlin/chain/Chain.kt | 4 ++-- src/main/kotlin/docker/DockerContainer.kt | 4 ++-- src/test/kotlin/CircularListTest.kt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/chain/Chain.kt b/src/main/kotlin/chain/Chain.kt index d7e673b..0765056 100644 --- a/src/main/kotlin/chain/Chain.kt +++ b/src/main/kotlin/chain/Chain.kt @@ -27,12 +27,12 @@ class Chain( /** Returns the last block in the chain. */ fun getLastBlock(): Block? { - return lock.withLock { blocks.lastOrNull() } + return lock.withLock { blocks.items.lastOrNull() } } /** Returns max 100 blocks [from slot][fromSlot].*/ fun getLastBlocks(fromSlot: Long): List { - return lock.withLock { blocks.takeLastWhile { it.slot > fromSlot } }.take(100) + return lock.withLock { blocks.items.takeLastWhile { it.slot > fromSlot } }.take(100) } /** Attempts to add each block one by one to the chain. */ diff --git a/src/main/kotlin/docker/DockerContainer.kt b/src/main/kotlin/docker/DockerContainer.kt index c17ef08..9d47253 100644 --- a/src/main/kotlin/docker/DockerContainer.kt +++ b/src/main/kotlin/docker/DockerContainer.kt @@ -27,8 +27,8 @@ data class DockerContainer( var updated: Long = System.currentTimeMillis(), var latestSnapshot: String? = null ) { - val averageCpuUsage get(): Double = cpuUsage.elements().average().takeIf { !it.isNaN() } ?: 0.0 - val averageMemoryUsage get(): Double = memoryUsage.elements().average().takeIf { !it.isNaN() } ?: 0.0 + val averageCpuUsage get(): Double = cpuUsage.items.average().takeIf { !it.isNaN() } ?: 0.0 + val averageMemoryUsage get(): Double = memoryUsage.items.average().takeIf { !it.isNaN() } ?: 0.0 } @Serializable diff --git a/src/test/kotlin/CircularListTest.kt b/src/test/kotlin/CircularListTest.kt index ecd64bd..c075545 100644 --- a/src/test/kotlin/CircularListTest.kt +++ b/src/test/kotlin/CircularListTest.kt @@ -13,6 +13,6 @@ class CircularListTest { fun circularTest() { val circularList = CircularList(3) for (i in 0..10) circularList.add(i) - assertEquals(circularList.elements(), listOf(8, 9, 10)) + assertEquals(circularList.items, listOf(8, 9, 10)) } } \ No newline at end of file From 2ea4b80f50d38814b7e7c790e1722c3ff32e474e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Thu, 15 Jan 2026 14:29:52 +0100 Subject: [PATCH 37/40] Removed logs. --- src/main/kotlin/docker/DockerProxy.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/kotlin/docker/DockerProxy.kt b/src/main/kotlin/docker/DockerProxy.kt index 708da3e..532aa0f 100644 --- a/src/main/kotlin/docker/DockerProxy.kt +++ b/src/main/kotlin/docker/DockerProxy.kt @@ -65,7 +65,6 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con fun sendDockerStatistics(block: Block, blockProducer: String, clusters: Map>) { val slot = block.slot val currentTime = System.currentTimeMillis() - println("Containers length before remove: ${localContainers.size}") localContainers.entries.removeIf { (_, container) -> currentTime - container.updated >= 30_000 } val mapped: List = localContainers.values.map { it.copy(id = networkMappings[it.id] ?: it.id) } @@ -92,7 +91,6 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con /** Starts a process of `docker stats` and keeps the [localStatistics] up to date. */ private fun listenForDockerStatistics() { - println("Started a docker stats process") val numberOfElements = (configuration.slotDuration / 1000).toInt() val json = Json { ignoreUnknownKeys = true @@ -106,7 +104,6 @@ abstract class DockerProxy(configuration: Configuration) : MigrationStrategy(con val reader = process.inputStream.bufferedReader() reader.readLines().forEach { line -> - println(line) val stats = json.decodeFromString(line) val pids = stats.pids.toIntOrNull() ?: 0 val cpuPercentage = stats.cpuPercentage.trim('%').toDoubleOrNull() ?: 0.0 From c008481235a507b5093f263c6f81cacc8d1ea4ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 28 Jan 2026 11:55:48 +0100 Subject: [PATCH 38/40] Added DHT node sharing via websocket. --- src/main/kotlin/network/rpc/RPCManager.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/kotlin/network/rpc/RPCManager.kt b/src/main/kotlin/network/rpc/RPCManager.kt index 30b1dea..f791c4b 100644 --- a/src/main/kotlin/network/rpc/RPCManager.kt +++ b/src/main/kotlin/network/rpc/RPCManager.kt @@ -7,6 +7,7 @@ import io.javalin.websocket.WsConnectContext import io.javalin.websocket.WsContext import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import logging.Logger import network.kademlia.Kademlia import java.util.concurrent.TimeUnit @@ -30,6 +31,19 @@ open class RPCManager(configuration: Configuration) : Kademlia(configuration) { webServer.ws("/") { it.onConnect(this::onConnect) it.onClose(this::onClose) + it.onMessage { context -> + val message = context.message() + when (message) { + "dht" -> { + context.send(Json.encodeToString(knownNodes.values)) + } + + else -> { + Logger.debug("A message of $message is being ignored via WS") + } + } + + } } } } @@ -47,6 +61,7 @@ open class RPCManager(configuration: Configuration) : Kademlia(configuration) { .add(webSocket) } sendToSubscribed(Topic.Logging, "Hello, this is Nion node!") + sendToSubscribed(Topic.Logging, Json.encodeToString(knownNodes.values)) } /** From e7467a5a34c91ff66b494729ecc026be107d7ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 28 Jan 2026 12:08:09 +0100 Subject: [PATCH 39/40] Added DHT node sharing via websocket. --- src/main/kotlin/network/rpc/RPCManager.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/network/rpc/RPCManager.kt b/src/main/kotlin/network/rpc/RPCManager.kt index f791c4b..e2daf41 100644 --- a/src/main/kotlin/network/rpc/RPCManager.kt +++ b/src/main/kotlin/network/rpc/RPCManager.kt @@ -35,7 +35,7 @@ open class RPCManager(configuration: Configuration) : Kademlia(configuration) { val message = context.message() when (message) { "dht" -> { - context.send(Json.encodeToString(knownNodes.values)) + context.send(Json.encodeToString(knownNodes.values.toList())) } else -> { @@ -61,7 +61,7 @@ open class RPCManager(configuration: Configuration) : Kademlia(configuration) { .add(webSocket) } sendToSubscribed(Topic.Logging, "Hello, this is Nion node!") - sendToSubscribed(Topic.Logging, Json.encodeToString(knownNodes.values)) + sendToSubscribed(Topic.Logging, Json.encodeToString(knownNodes.values.toList())) } /** From ca480b113ef38196a54761f1827f5f0a7d2b10f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihael=20Ber=C4=8Di=C4=8D?= Date: Wed, 28 Jan 2026 12:11:54 +0100 Subject: [PATCH 40/40] Added DHT node sharing via websocket. --- src/main/kotlin/network/rpc/RPCManager.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/network/rpc/RPCManager.kt b/src/main/kotlin/network/rpc/RPCManager.kt index e2daf41..3135b8c 100644 --- a/src/main/kotlin/network/rpc/RPCManager.kt +++ b/src/main/kotlin/network/rpc/RPCManager.kt @@ -61,7 +61,7 @@ open class RPCManager(configuration: Configuration) : Kademlia(configuration) { .add(webSocket) } sendToSubscribed(Topic.Logging, "Hello, this is Nion node!") - sendToSubscribed(Topic.Logging, Json.encodeToString(knownNodes.values.toList())) + sendToSubscribed(Topic.Logging, knownNodes.values.toList()) } /**