Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Added new TL with kotlinx-serialization support
- All cryptography moved to `ton-kotlin-crypto` module under `org.ton.kotlin.crypto` package
- Updated Ktor to 3.3.0

### Deprecated

Expand Down
4 changes: 2 additions & 2 deletions adnl/src/connection/AdnlClientImpl.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package org.ton.adnl.connection

import io.ktor.utils.io.core.*
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.withTimeout
import kotlinx.io.bytestring.ByteString
import kotlinx.io.readByteArray
import org.ton.api.adnl.message.AdnlMessageAnswer
import org.ton.api.adnl.message.AdnlMessageQuery
import org.ton.api.liteserver.LiteServerDesc
Expand All @@ -28,7 +28,7 @@ public class AdnlClientImpl(
), context
)
AdnlMessageAnswer.decodeBoxed(
response.body.readBytes()
response.body.readByteArray()
).answer.toByteArray()
}
} catch (e: Throwable) {
Expand Down
30 changes: 16 additions & 14 deletions adnl/src/connection/AdnlConnection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package org.ton.adnl.connection

import io.ktor.utils.io.*
import io.ktor.utils.io.core.*
import io.ktor.utils.io.errors.*
import kotlinx.atomicfu.atomic
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.io.*
import kotlinx.io.Buffer
import org.ton.adnl.network.TcpClient
import org.ton.api.liteserver.LiteServerDesc
import org.ton.kotlin.crypto.*
Expand Down Expand Up @@ -66,10 +67,11 @@ public class AdnlConnection(
}
}

connection.output.writePacket {
writeFully(serverPublicKey.computeShortId().toByteArray())
val handshakePacket = Buffer().apply {
write(serverPublicKey.computeShortId())
writeFully(serverPublicKey.encryptToByteArray(nonce))
}
connection.output.writePacket(handshakePacket)
connection.output.flush()

val cipher = ChannelCipher(nonce)
Expand Down Expand Up @@ -127,7 +129,7 @@ public class AdnlConnection(
} finally {
output.flush()
if (closeChannel) {
output.close()
output.flushAndClose()
}
}
}
Expand All @@ -150,20 +152,20 @@ public class AdnlConnection(
private suspend fun readRaw(
input: ByteReadChannel,
cipher: AesCtr
): ByteReadPacket {
val encryptedLength = input.readPacket(4).readBytes()
): Source {
val encryptedLength = input.readPacket(4).readByteArray()
val plainLength = ByteArray(4)
cipher.processBytes(encryptedLength, plainLength)

val length = ByteReadPacket(plainLength).readIntLittleEndian()
val length = ByteReadPacket(plainLength).readIntLe()
check(length in 32..(1 shl 24)) { "Invalid length" }
val encryptedData = input.readPacket(length).readBytes()
val encryptedData = input.readPacket(length).readByteArray()
val plainData = ByteArray(length)
cipher.processBytes(encryptedData, plainData)

val data = ByteReadPacket(plainData)
val payload = data.readBytes((data.remaining - 32).toInt())
val hash = data.readBytes(32)
val payload = data.readByteArray((data.remaining - 32).toInt())
val hash = data.readByteArray(32)

require(sha256(payload).contentEquals(hash)) {
"sha256 mismatch"
Expand All @@ -177,27 +179,27 @@ public class AdnlConnection(
private suspend fun writeRaw(
output: ByteWriteChannel,
cipher: AesCtr,
packet: ByteReadPacket
packet: Source
) {
val dataSize = (packet.remaining + 32 + 32).toInt()
require(dataSize in 32..(1 shl 24)) { "Invalid packet size: $dataSize" }
val nonce = SecureRandom.nextBytes(32)
val payload = packet.readBytes()
val payload = packet.readByteArray()

val hash = Sha256().apply {
update(nonce)
update(payload)
}.digest()

val data = buildPacket {
writeIntLittleEndian(dataSize)
writeIntLe(dataSize)
writeFully(nonce)
writeFully(payload)
writeFully(hash)
}

val encryptedData = ByteArray(data.remaining.toInt())
cipher.processBytes(data.readBytes(), encryptedData)
cipher.processBytes(data.readByteArray(), encryptedData)
output.writeFully(encryptedData)
}

Expand Down
4 changes: 2 additions & 2 deletions adnl/src/connection/AdnlRequestData.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package org.ton.adnl.connection

import io.ktor.utils.io.core.*
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Job
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.io.Source
import org.ton.api.http.functions.HttpRequest
import kotlin.coroutines.CoroutineContext

Expand All @@ -15,7 +15,7 @@ public class AdnlRequestData(

public class AdnlResponseData(
public val requestTime: Instant,
public val body: ByteReadPacket,
public val body: Source,
public val callContext: CoroutineContext
) {
public val responseTime: Instant = Clock.System.now()
Expand Down
6 changes: 3 additions & 3 deletions adnl/src/engine/AdnlNetworkEngine.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package org.ton.adnl.engine

import io.ktor.utils.io.core.*
import kotlinx.io.Source
import org.ton.api.adnl.AdnlAddressUdp

public interface AdnlNetworkEngine {
public suspend fun sendDatagram(adnlAddress: AdnlAddressUdp, payload: ByteReadPacket)
public suspend fun receiveDatagram(): Pair<AdnlAddressUdp, ByteReadPacket>
public suspend fun sendDatagram(adnlAddress: AdnlAddressUdp, payload: Source)
public suspend fun receiveDatagram(): Pair<AdnlAddressUdp, Source>
}
13 changes: 9 additions & 4 deletions adnl/src@jvm/engine/CIOAdnlNetworkEngine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package org.ton.adnl.engine

import io.ktor.network.selector.*
import io.ktor.network.sockets.*
import io.ktor.utils.io.core.*
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.newFixedThreadPoolContext
import kotlinx.coroutines.runBlocking
import kotlinx.io.Source
import org.ton.adnl.ipv4
import org.ton.adnl.utils.toAdnlUdpAddress
import org.ton.adnl.utils.toSocketAddress
Expand All @@ -16,14 +17,18 @@ public class CIOAdnlNetworkEngine(
public constructor(port: Int) : this(AdnlAddressUdp(ipv4("0.0.0.0"), port))

public val socket: BoundDatagramSocket =
aSocket(ActorSelectorManager(DISPATCHER)).udp().bind(localAddress.toSocketAddress())
aSocket(ActorSelectorManager(DISPATCHER)).udp().let {
runBlocking {
it.bind(localAddress.toSocketAddress())
}
}

override suspend fun sendDatagram(adnlAddress: AdnlAddressUdp, payload: ByteReadPacket) {
override suspend fun sendDatagram(adnlAddress: AdnlAddressUdp, payload: Source) {
val datagram = Datagram(payload, adnlAddress.toSocketAddress())
socket.send(datagram)
}

override suspend fun receiveDatagram(): Pair<AdnlAddressUdp, ByteReadPacket> {
override suspend fun receiveDatagram(): Pair<AdnlAddressUdp, Source> {
val datagram = socket.receive()
val adnlAddress = datagram.address.toAdnlUdpAddress()
val payload = datagram.packet
Expand Down
2 changes: 1 addition & 1 deletion adnl/src@jvm/network/TcpClientImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public actual class TcpClientImpl actual constructor(
get() = connection.output

actual override suspend fun connect(host: String, port: Int) {
socket = aSocket(selectorManager).tcpNoDelay().tcp().connect(host, port)
socket = aSocket(selectorManager).tcp().connect(host, port)
connection = socket.connection()
isClosed = false
}
Expand Down
12 changes: 6 additions & 6 deletions bitstring/test/BitStringTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ class BitStringTest {

@Test
fun `toString on a zero number`() {
assertEquals("0", BitString(List(4) { false }).toHex())
assertEquals("00000000", BitString(List(32) { false }).toHex())
assertEquals("0000000000000000", BitString(List(64) { false }).toHex())
assertEquals("0", BitString(List(4) { false }).toHexString())
assertEquals("00000000", BitString(List(32) { false }).toHexString())
assertEquals("0000000000000000", BitString(List(64) { false }).toHexString())
}
}

Expand All @@ -117,11 +117,11 @@ fun assertBitString(binary: String, hex: String) {
val hexBits = BitString(hex)

assertEquals(binaryBits, hexBits)
assertEquals(hex, binaryBits.toHex())
assertEquals(hex, hexBits.toHex())
assertEquals(hex, binaryBits.toHexString())
assertEquals(hex, hexBits.toHexString())
assertEquals(binary, binaryBits.toBooleanArray().joinToBits())
assertEquals(binary, hexBits.toBooleanArray().joinToBits())
assertEquals(binaryBits.toHex(), hexBits.toHex())
assertEquals(binaryBits.toHexString(), hexBits.toHexString())
assertContentEquals(binaryBits.toBooleanArray(), hexBits.toBooleanArray())
assertContentEquals(binaryBits.toByteArray(), hexBits.toByteArray())
assertEquals(BitString(binaryBits.size), BitString(hexBits.size))
Expand Down
2 changes: 1 addition & 1 deletion block-tlb/src/AddrStd.kt
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public data class AddrStd(
Base64.encode(data)
}
} else {
"${address.workchainId}:${address.address.toHex()}"
"${address.workchainId}:${address.address.toHexString()}"
}
}

Expand Down
2 changes: 1 addition & 1 deletion block-tlb/test/StateInitTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ class StateInitTest {
assertEquals(BitString(publicKey), loadBits(256))
}

assertEquals(hash, stateInitCell.hash().toHex().lowercase())
assertEquals(hash, stateInitCell.hash().toHexString().lowercase())
}
}
4 changes: 2 additions & 2 deletions build-logic/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ repositories {
}

dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20")
implementation("com.vanniktech:gradle-maven-publish-plugin:0.28.0")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.20")
implementation("com.vanniktech:gradle-maven-publish-plugin:0.34.0")
}
10 changes: 4 additions & 6 deletions build-logic/src/main/kotlin/multiplatform.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ kotlin {
// explicitApiWarning()
explicitApi()

//optin
compilerOptions {
freeCompilerArgs.add("-Xexpect-actual-classes")
}

jvm {
compilations.all {
kotlinOptions {
jvmTarget = "1.8"
}
}

}

sourceSets {
Expand Down
6 changes: 2 additions & 4 deletions build-logic/src/main/kotlin/publish.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import com.vanniktech.maven.publish.SonatypeHost

plugins {
id("com.vanniktech.maven.publish")
Expand All @@ -9,7 +8,7 @@ mavenPublishing {
name = project.name
description = "Kotlin/Multiplatform SDK for The Open Network"
inceptionYear = "2025"
url = "https://github.com/ton-community/ton-kotlin"
url = "https://github.com/ton-blockchain/ton-kotlin"

licenses {
license {
Expand All @@ -27,10 +26,9 @@ mavenPublishing {
}
}
scm {
url = "https://github.com/ton-community/ton-kotlin"
url = "https://github.com/ton-blockchain/ton-kotlin"
}
}

publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
signAllPublications()
}
2 changes: 1 addition & 1 deletion libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[versions]
datetime = "0.5.0" # https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-datetime
benchmark = "0.4.7" # https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-benchmark-runtime
ktor = "2.3.7" # https://search.maven.org/artifact/io.ktor/ktor
ktor = "3.3.0" # https://central.sonatype.com/artifact/io.ktor/ktor-server/versions
bignum = "0.3.8" # https://search.maven.org/artifact/com.ionspin.kotlin/bignum
cache4k = "0.12.0" # https://central.sonatype.com/namespace/io.github.reactivecircus.cache4k
bcv = "0.13.2"
Expand Down
2 changes: 2 additions & 0 deletions tl-legacy/src/commonMain/kotlin/AbstractTlCombinator.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("DEPRECATION")

package org.ton.tl

import kotlin.reflect.KClass
Expand Down
2 changes: 2 additions & 0 deletions tl-legacy/src/commonMain/kotlin/TlCodec.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("DEPRECATION")

package org.ton.tl

@Deprecated(DEPRECATION_MESSAGE)
Expand Down
2 changes: 2 additions & 0 deletions tl-legacy/src/commonMain/kotlin/TlCombinator.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("DEPRECATION")

package org.ton.tl

import kotlin.reflect.KClass
Expand Down
2 changes: 2 additions & 0 deletions tl-legacy/src/commonMain/kotlin/TlConstructor.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("DEPRECATION")

package org.ton.tl

import org.ton.kotlin.crypto.crc32
Expand Down
2 changes: 2 additions & 0 deletions tl-legacy/src/commonMain/kotlin/TlDecoder.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("DEPRECATION")

package org.ton.tl

import kotlinx.io.Buffer
Expand Down
2 changes: 2 additions & 0 deletions tl-legacy/src/commonMain/kotlin/TlEncoder.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("DEPRECATION")

package org.ton.tl

import kotlinx.io.Buffer
Expand Down
2 changes: 2 additions & 0 deletions tl-legacy/src/commonMain/kotlin/TlReader.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("DEPRECATION", "NOTHING_TO_INLINE")

package org.ton.tl

import kotlinx.io.*
Expand Down
2 changes: 2 additions & 0 deletions tl-legacy/src/commonMain/kotlin/TlWriter.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("DEPRECATION")

package org.ton.tl

import kotlinx.io.*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("DEPRECATION")

package org.ton.tl.constructors

import org.ton.tl.DEPRECATION_MESSAGE
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@file:Suppress("OPT_IN_USAGE")
@file:Suppress("OPT_IN_USAGE", "DEPRECATION")

package org.ton.tl.constructors

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("DEPRECATION")

package org.ton.tl.constructors

import org.ton.tl.*
Expand Down
1 change: 1 addition & 0 deletions tl/src/commonMain/kotlin/internal/TlDecoderImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ internal open class TlDecoderImpl(

override fun decodeInline(descriptor: SerialDescriptor): Decoder = this

@Suppress("UNCHECKED_CAST")
@OptIn(InternalSerializationApi::class)
override fun <T> decodeSerializableValue(deserializer: DeserializationStrategy<T>): T {
if (tl.boxed && deserializer !is AbstractPolymorphicSerializer<*>) {
Expand Down
Loading