From 7eb82e9b04a2e518182ebfc56c165fbfcc916be9 Mon Sep 17 00:00:00 2001 From: Andrey Pfau Date: Wed, 21 Feb 2024 11:46:51 +0700 Subject: [PATCH] refactor byte strings --- adnl/src/Adnl.kt | 92 ---------- adnl/src/AdnlPeers.kt | 125 -------------- adnl/src/connection/AdnlClient.kt | 3 +- adnl/src/connection/AdnlClientImpl.kt | 24 +-- adnl/src/connection/AdnlConnection.kt | 7 +- adnl/src/network/IPAddress.kt | 3 +- adnl/src/peer/AdnlMessagePartDecoder.kt | 45 ----- adnl/src/peer/AdnlMessagePartEncoder.kt | 32 ---- adnl/src/resolver/AdnlAddressResolver.kt | 10 -- adnl/src/resolver/MapAdnlAddressResolver.kt | 11 -- build.gradle.kts | 3 +- contract/src/CellString.kt | 9 +- contract/src/wallet/MessageText.kt | 8 +- contract/src/wallet/WalletV3Contract.kt | 4 +- contract/src/wallet/WalletV4R2Contract.kt | 4 +- libs.versions.toml | 2 + liteapi-tl/src/LiteApiClient.kt | 20 +-- .../src/liteserver/LiteServerAccountId.kt | 13 +- .../src/liteserver/LiteServerAccountState.kt | 4 + .../src/liteserver/LiteServerAllShardsInfo.kt | 3 + .../src/liteserver/LiteServerBlockData.kt | 2 + .../src/liteserver/LiteServerBlockHeader.kt | 2 + .../src/liteserver/LiteServerBlockLinkBack.kt | 4 + .../liteserver/LiteServerBlockLinkForward.kt | 3 + .../src/liteserver/LiteServerBlockState.kt | 4 + .../liteserver/LiteServerBlockTransactions.kt | 2 + .../src/liteserver/LiteServerConfigInfo.kt | 3 + .../liteserver/LiteServerMasterchainInfo.kt | 2 + .../LiteServerMasterchainInfoExt.kt | 2 + .../liteserver/LiteServerRunMethodResult.kt | 37 +--- .../src/liteserver/LiteServerShardInfo.kt | 3 + .../src/liteserver/LiteServerSignature.kt | 6 +- .../src/liteserver/LiteServerTransactionId.kt | 8 +- .../liteserver/LiteServerTransactionId3.kt | 2 + .../liteserver/LiteServerTransactionInfo.kt | 3 + .../liteserver/LiteServerTransactionList.kt | 2 + .../liteserver/LiteServerValidatorStats.kt | 3 + .../functions/LiteServerGetTransactions.kt | 7 +- .../functions/LiteServerGetValidatorStats.kt | 2 + .../liteserver/functions/LiteServerQuery.kt | 2 + .../functions/LiteServerRunSmcMethod.kt | 2 + .../functions/LiteServerSendMessage.kt | 2 + liteclient/src/LiteClient.kt | 32 ++-- tl/build.gradle.kts | 1 + tl/src/ByteString.kt | 159 ------------------ tl/src/ByteStringBase64Serializer.kt | 24 +++ tl/src/TlDecoder.kt | 29 +++- tl/src/TlEncoder.kt | 17 +- tl/src/TlReader.kt | 17 +- tl/src/TlWriter.kt | 70 ++++---- tl/src/constructors/BytesTlConstructor.kt | 2 +- tonapi-tl/src/SignedTlObject.kt | 2 +- tonapi-tl/src/adnl/AdnlAddress.kt | 9 +- tonapi-tl/src/adnl/AdnlAddressList.kt | 2 - tonapi-tl/src/adnl/AdnlIdShort.kt | 2 + tonapi-tl/src/adnl/AdnlNode.kt | 5 - tonapi-tl/src/adnl/AdnlPacketContents.kt | 10 +- tonapi-tl/src/adnl/AdnlProxy.kt | 4 + tonapi-tl/src/adnl/AdnlProxyTo.kt | 18 +- tonapi-tl/src/adnl/AdnlProxyToSign.kt | 7 +- .../src/adnl/message/AdnlMessageAnswer.kt | 10 +- .../adnl/message/AdnlMessageConfirmChannel.kt | 21 +-- .../adnl/message/AdnlMessageCreateChannel.kt | 13 +- .../src/adnl/message/AdnlMessageCustom.kt | 4 +- tonapi-tl/src/adnl/message/AdnlMessagePart.kt | 15 +- .../src/adnl/message/AdnlMessageQuery.kt | 5 +- tonapi-tl/src/control/ControlConfigLocal.kt | 4 +- tonapi-tl/src/dht/DhtKey.kt | 21 +-- tonapi-tl/src/dht/DhtKeyDescription.kt | 16 +- tonapi-tl/src/dht/DhtNode.kt | 6 +- tonapi-tl/src/dht/DhtValue.kt | 12 +- tonapi-tl/src/dht/functions/DhtFindValue.kt | 4 +- tonapi-tl/src/http/HttpPayloadPart.kt | 28 +-- .../http/functions/HttpGetNextPayloadPart.kt | 20 +-- tonapi-tl/src/http/functions/HttpRequest.kt | 2 + tonapi-tl/src/overlay/OverlayNode.kt | 22 +-- tonapi-tl/src/overlay/OverlayNodeToSign.kt | 2 + tonapi-tl/src/pk/aes.kt | 4 +- tonapi-tl/src/pk/ed25519.kt | 16 +- tonapi-tl/src/pk/overlay.kt | 4 +- tonapi-tl/src/pk/unenc.kt | 8 +- tonapi-tl/src/pub/ed25519.kt | 14 +- tonapi-tl/src/pub/pub.kt | 11 +- tonapi-tl/src/rldp/RldpAnswer.kt | 3 + tonapi-tl/src/rldp/RldpComplete.kt | 2 + tonapi-tl/src/rldp/RldpConfirm.kt | 2 + tonapi-tl/src/rldp/RldpMessage.kt | 2 +- tonapi-tl/src/rldp/RldpMessageData.kt | 3 + tonapi-tl/src/rldp/RldpMessagePart.kt | 2 +- tonapi-tl/src/rldp/RldpMessagePartData.kt | 3 + tonapi-tl/src/rldp/RldpQuery.kt | 12 +- .../src/tcp/TcpAuthentificationComplete.kt | 20 +-- tonapi-tl/src/tcp/TcpAuthentificationNonce.kt | 20 +-- tonapi-tl/src/tonnode/TonNodeBlockId.kt | 2 +- tonapi-tl/src/tonnode/TonNodeBlockIdExt.kt | 47 ++---- .../src/tonnode/TonNodeZeroStateIdExt.kt | 9 +- tvm/src/cell/CellBuilder.kt | 14 +- 97 files changed, 431 insertions(+), 907 deletions(-) delete mode 100644 adnl/src/Adnl.kt delete mode 100644 adnl/src/AdnlPeers.kt delete mode 100644 adnl/src/peer/AdnlMessagePartDecoder.kt delete mode 100644 adnl/src/peer/AdnlMessagePartEncoder.kt delete mode 100644 adnl/src/resolver/AdnlAddressResolver.kt delete mode 100644 adnl/src/resolver/MapAdnlAddressResolver.kt delete mode 100644 tl/src/ByteString.kt create mode 100644 tl/src/ByteStringBase64Serializer.kt diff --git a/adnl/src/Adnl.kt b/adnl/src/Adnl.kt deleted file mode 100644 index 5fe673ca..00000000 --- a/adnl/src/Adnl.kt +++ /dev/null @@ -1,92 +0,0 @@ -package org.ton.adnl - -import org.ton.adnl.engine.AdnlNetworkEngine -import org.ton.api.adnl.AdnlAddressList -import org.ton.api.adnl.AdnlIdShort -import org.ton.api.pk.PrivateKey -import org.ton.api.pub.PublicKey -import org.ton.tl.ByteString -import kotlin.time.Duration -import kotlin.time.Duration.Companion.seconds - -public interface Adnl { - public val hugePacketMaxSize: Int get() = 1024 * 8 - public val mtu: Int get() = 1024 - public val networkEngine: AdnlNetworkEngine - - public fun addLocalId(privateKey: PrivateKey) - - public suspend fun sendMessage( - src: AdnlIdShort, - dest: AdnlIdShort, - data: ByteString - ) - - public suspend fun sendQuery( - src: AdnlIdShort, - dest: AdnlIdShort, - data: ByteString, - timeout: Duration = 15.seconds, - maxAnswerSize: Int = Int.MAX_VALUE - ) - - public fun addPeer(localId: AdnlIdShort, remoteKey: PublicKey, addressList: AdnlAddressList) - - public fun subscribeMessage( - dest: AdnlIdShort, - handler: MessageHandler - ): MessageHandler - - public fun subscribeQuery( - dest: AdnlIdShort, - handler: QueryHandler - ): QueryHandler - - public fun interface MessageHandler { - public fun onMessage(src: AdnlIdShort, dest: AdnlIdShort, message: ByteString) - } - - public fun interface QueryHandler { - public fun onQuery(src: AdnlIdShort, dest: AdnlIdShort, query: ByteString): ByteString - } - - public companion object { - public fun create( - networkEngine: AdnlNetworkEngine - ): Adnl = AdnlImpl(networkEngine) - } -} - -private class AdnlImpl( - override val networkEngine: AdnlNetworkEngine -) : Adnl { - override fun addLocalId(privateKey: PrivateKey) { - TODO("Not yet implemented") - } - - override suspend fun sendMessage(src: AdnlIdShort, dest: AdnlIdShort, data: ByteString) { - TODO("Not yet implemented") - } - - override suspend fun sendQuery( - src: AdnlIdShort, - dest: AdnlIdShort, - data: ByteString, - timeout: Duration, - maxAnswerSize: Int - ) { - TODO("Not yet implemented") - } - - override fun addPeer(localId: AdnlIdShort, remoteKey: PublicKey, addressList: AdnlAddressList) { - TODO("Not yet implemented") - } - - override fun subscribeMessage(dest: AdnlIdShort, handler: Adnl.MessageHandler): Adnl.MessageHandler { - TODO("Not yet implemented") - } - - override fun subscribeQuery(dest: AdnlIdShort, handler: Adnl.QueryHandler): Adnl.QueryHandler { - TODO("Not yet implemented") - } -} diff --git a/adnl/src/AdnlPeers.kt b/adnl/src/AdnlPeers.kt deleted file mode 100644 index d273fb9f..00000000 --- a/adnl/src/AdnlPeers.kt +++ /dev/null @@ -1,125 +0,0 @@ -package org.ton.adnl - -import org.ton.adnl.peer.AdnlMessagePartDecoder -import org.ton.adnl.peer.AdnlMessagePartEncoder -import org.ton.api.adnl.AdnlIdShort -import org.ton.api.adnl.AdnlPacketContents -import org.ton.api.adnl.message.* -import org.ton.tl.ByteString -import kotlin.time.Duration -import kotlin.time.Duration.Companion.seconds - -public interface AdnlPeerSession { - public val adnl: Adnl - public val hugePacketMaxSize: Int get() = adnl.hugePacketMaxSize + 128 - public val mtu: Int get() = adnl.mtu + 128 - - public suspend fun sendMessages( - vararg messages: AdnlMessage - ) - - public suspend fun sendQuery( - data: ByteString, - timeout: Duration = 15.seconds - ): ByteString - - public fun handlePacket(packet: AdnlPacketContents) - - public fun handleMessage(message: AdnlMessage): Unit = when (message) { - is AdnlMessageAnswer -> handleMessage(message) - is AdnlMessageConfirmChannel -> handleMessage(message) - is AdnlMessageCreateChannel -> handleMessage(message) - is AdnlMessageCustom -> handleMessage(message) - is AdnlMessageNop -> handleMessage(message) - is AdnlMessagePart -> handleMessage(message) - is AdnlMessageQuery -> handleMessage(message) - is AdnlMessageReinit -> handleMessage(message) - } - - public fun handleMessage(message: AdnlMessageCreateChannel) - public fun handleMessage(message: AdnlMessageConfirmChannel) - public fun handleMessage(message: AdnlMessageCustom) - public fun handleMessage(message: AdnlMessageNop) {} - public fun handleMessage(message: AdnlMessageReinit) - public fun handleMessage(message: AdnlMessageQuery) - public fun handleMessage(message: AdnlMessageAnswer) - public fun handleMessage(message: AdnlMessagePart) -} - - -public interface AdnlPeer { - public suspend fun sendMessages( - src: AdnlIdShort, - vararg messages: AdnlMessage - ) - - public suspend fun sendQuery( - src: AdnlIdShort, - data: ByteString, - timeout: Duration = 15.seconds - ): ByteString - - public fun handlePacket(dest: AdnlIdShort, packet: AdnlPacketContents) -} - -internal open class AdnlPeerSessionImpl( - override val adnl: Adnl -) : AdnlPeerSession { - private val messagePartDecoder = AdnlMessagePartDecoder(hugePacketMaxSize) - private val messagePartEncoder = AdnlMessagePartEncoder(mtu, hugePacketMaxSize) - - override suspend fun sendMessages(vararg messages: AdnlMessage) { - val newMessages = ArrayList() - messages.forEach { message -> - if (AdnlMessage.sizeOf(message) <= mtu) { - newMessages.add(message) - } else { - newMessages.addAll(messagePartEncoder.encode(message)) - } - } - sendRawMessages(newMessages) - } - - override suspend fun sendQuery(data: ByteString, timeout: Duration): ByteString { - TODO("Not yet implemented") - } - - override fun handlePacket(packet: AdnlPacketContents) { - TODO("Not yet implemented") - } - - override fun handleMessage(message: AdnlMessageCreateChannel) { - TODO("Not yet implemented") - } - - override fun handleMessage(message: AdnlMessageConfirmChannel) { - TODO("Not yet implemented") - } - - override fun handleMessage(message: AdnlMessageCustom) { - println("Custom: ${message.data}") - } - - override fun handleMessage(message: AdnlMessageReinit) { - TODO("Not yet implemented") - } - - override fun handleMessage(message: AdnlMessageQuery) { - TODO("Not yet implemented") - } - - override fun handleMessage(message: AdnlMessageAnswer) { - TODO("Not yet implemented") - } - - override fun handleMessage(message: AdnlMessagePart) { - val decodedMessage = messagePartDecoder.decode(message) - if (decodedMessage != null) { - handleMessage(decodedMessage) - } - } - - private suspend fun sendRawMessages(messages: List) { - adnl - } -} diff --git a/adnl/src/connection/AdnlClient.kt b/adnl/src/connection/AdnlClient.kt index 8d7d89bb..48da1b62 100644 --- a/adnl/src/connection/AdnlClient.kt +++ b/adnl/src/connection/AdnlClient.kt @@ -1,8 +1,7 @@ package org.ton.adnl.connection -import io.ktor.utils.io.core.* import kotlin.time.Duration public interface AdnlClient { - public suspend fun sendQuery(data: ByteReadPacket, timeout: Duration): ByteReadPacket + public suspend fun sendQuery(data: ByteArray, timeout: Duration): ByteArray } diff --git a/adnl/src/connection/AdnlClientImpl.kt b/adnl/src/connection/AdnlClientImpl.kt index e40ce211..35b5039d 100644 --- a/adnl/src/connection/AdnlClientImpl.kt +++ b/adnl/src/connection/AdnlClientImpl.kt @@ -3,39 +3,33 @@ 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 org.ton.api.adnl.message.AdnlMessageAnswer import org.ton.api.adnl.message.AdnlMessageQuery import org.ton.api.liteserver.LiteServerDesc -import org.ton.tl.ByteString -import org.ton.tl.asByteString import kotlin.random.Random import kotlin.time.Duration public class AdnlClientImpl( private val liteServerDesc: LiteServerDesc ) : AdnlClient { - override suspend fun sendQuery(data: ByteReadPacket, timeout: Duration): ByteReadPacket { + override suspend fun sendQuery(data: ByteArray, timeout: Duration): ByteArray { val adnlConnection = connectionPool.selectConnection(liteServerDesc) - val queryId = ByteString.of(*Random.nextBytes(32)) + val queryId = ByteString(*Random.nextBytes(32)) val context = SupervisorJob() - val queryData = data.readBytes() try { return withTimeout(timeout) { val response = adnlConnection.execute( AdnlRequestData( - buildPacket { - AdnlMessageQuery.encodeBoxed( - this, AdnlMessageQuery(queryId, queryData.asByteString()) - ) - }.readBytes(), + AdnlMessageQuery.encodeToByteArray( + AdnlMessageQuery(queryId, ByteString(*data)), true + ), context ), context ) - ByteReadPacket( - AdnlMessageAnswer.decodeBoxed( - response.body - ).answer.toByteArray() - ) + AdnlMessageAnswer.decodeBoxed( + response.body.readBytes() + ).answer.toByteArray() } } catch (e: Throwable) { throw e diff --git a/adnl/src/connection/AdnlConnection.kt b/adnl/src/connection/AdnlConnection.kt index b4c73ce2..32b3624b 100644 --- a/adnl/src/connection/AdnlConnection.kt +++ b/adnl/src/connection/AdnlConnection.kt @@ -14,7 +14,6 @@ import kotlinx.datetime.Instant import org.ton.adnl.network.TcpClient import org.ton.api.liteserver.LiteServerDesc import org.ton.crypto.SecureRandom -import org.ton.tl.writeByteString import kotlin.coroutines.CoroutineContext import kotlin.time.Duration import kotlin.time.Duration.Companion.ZERO @@ -67,7 +66,7 @@ public class AdnlConnection( } connection.output.writePacket { - writeByteString(liteServerDesc.id.toAdnlIdShort().id) + writeFully(liteServerDesc.id.toAdnlIdShort().id.toByteArray()) writeFully(liteServerDesc.id.encrypt(nonce)) } connection.output.flush() @@ -185,8 +184,8 @@ public class AdnlConnection( val payload = packet.readBytes() val hash = SHA256().apply { - write(nonce) - write(payload) + update(nonce) + update(payload) }.digest() val data = buildPacket { diff --git a/adnl/src/network/IPAddress.kt b/adnl/src/network/IPAddress.kt index 7cb9222b..82a1548e 100644 --- a/adnl/src/network/IPAddress.kt +++ b/adnl/src/network/IPAddress.kt @@ -1,5 +1,6 @@ package org.ton.adnl.network +import kotlinx.io.bytestring.ByteString import org.ton.adnl.ipv4 import org.ton.api.adnl.AdnlAddress import org.ton.api.adnl.AdnlAddressUdp @@ -54,7 +55,7 @@ public data class IPv6Address( override val host: String get() = TODO() - override fun toAdnlAddress(): AdnlAddressUdp6 = AdnlAddressUdp6(address, port) + override fun toAdnlAddress(): AdnlAddressUdp6 = AdnlAddressUdp6(ByteString(address), port) override fun toString(): String = "$host:$port" } diff --git a/adnl/src/peer/AdnlMessagePartDecoder.kt b/adnl/src/peer/AdnlMessagePartDecoder.kt deleted file mode 100644 index f0217d20..00000000 --- a/adnl/src/peer/AdnlMessagePartDecoder.kt +++ /dev/null @@ -1,45 +0,0 @@ -package org.ton.adnl.peer - -import org.ton.api.adnl.message.AdnlMessage -import org.ton.api.adnl.message.AdnlMessagePart -import org.ton.tl.asByteString - -public class AdnlMessagePartDecoder( - private val maxSize: Int = 1024 * 8 -) { - private var messagePayload = EMPTY_BYTES - private var messageHash = ZERO_HASH - private var messageOffset = 0 - - public fun decode(message: AdnlMessagePart): AdnlMessage? { - check(message.totalSize <= maxSize) { "too big message: size=${message.totalSize}" } - check(message.data.size + message.offset <= message.totalSize) { "bad part" } - check(message.hash == ZERO_HASH) { "zero hash" } - check(message.totalSize == messagePayload.size) { "invalid size" } - - if (message.hash != messageHash) { - messageHash = if (message.offset == 0) message.hash else ZERO_HASH - messagePayload = ByteArray(message.totalSize) - } - - val currentMessageOffset = messageOffset - if (message.offset == currentMessageOffset) { - message.data.copyInto(messagePayload, message.offset) - val totalSize = currentMessageOffset + message.data.size - messageOffset = totalSize - if (totalSize == messagePayload.size) { - val actualMessageHash = io.github.andreypfau.kotlinx.crypto.sha2.sha256(messagePayload) - check(actualMessageHash.asByteString() == messageHash) { - "hash mismatch, expected: $messageHash, actual: $actualMessageHash" - } - return AdnlMessage.decodeBoxed(messagePayload) - } - } - return null - } - - private companion object { - private val ZERO_HASH = ByteArray(32).asByteString() - private val EMPTY_BYTES = ByteArray(0) - } -} diff --git a/adnl/src/peer/AdnlMessagePartEncoder.kt b/adnl/src/peer/AdnlMessagePartEncoder.kt deleted file mode 100644 index 026c3728..00000000 --- a/adnl/src/peer/AdnlMessagePartEncoder.kt +++ /dev/null @@ -1,32 +0,0 @@ -package org.ton.adnl.peer - -import io.github.andreypfau.kotlinx.crypto.sha2.sha256 -import org.ton.api.adnl.message.AdnlMessage -import org.ton.api.adnl.message.AdnlMessagePart -import org.ton.tl.asByteString - -public class AdnlMessagePartEncoder( - public val mtu: Int, - public val maxSize: Int = 1024 * 8 -) { - public fun encode(message: AdnlMessage): List { - val newMessages = ArrayList() - val b = AdnlMessage.encodeToByteArray(message, boxed = true) - check(b.size <= maxSize) - val hash = sha256(b).asByteString() - val size = b.size - var offset = 0 - while (offset < size) { - val data = b.copyOfRange(offset, minOf(offset + mtu, b.size)) - val partMessage = AdnlMessagePart( - hash, - size, - offset, - data.asByteString() - ) - newMessages.add(partMessage) - offset += mtu - } - return newMessages - } -} diff --git a/adnl/src/resolver/AdnlAddressResolver.kt b/adnl/src/resolver/AdnlAddressResolver.kt deleted file mode 100644 index 4e7c0729..00000000 --- a/adnl/src/resolver/AdnlAddressResolver.kt +++ /dev/null @@ -1,10 +0,0 @@ -package org.ton.adnl.resolver - -import org.ton.api.adnl.AdnlAddress -import org.ton.api.adnl.AdnlIdShort -import org.ton.api.pub.PublicKey - -public interface AdnlAddressResolver { - public suspend fun resolve(publicKey: PublicKey): List? = resolve(publicKey.toAdnlIdShort())?.second - public suspend fun resolve(address: AdnlIdShort): Pair>? -} diff --git a/adnl/src/resolver/MapAdnlAddressResolver.kt b/adnl/src/resolver/MapAdnlAddressResolver.kt deleted file mode 100644 index 5476832b..00000000 --- a/adnl/src/resolver/MapAdnlAddressResolver.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.ton.adnl.resolver - -import org.ton.api.adnl.AdnlAddress -import org.ton.api.adnl.AdnlIdShort -import org.ton.api.pub.PublicKey - -public class MapAdnlAddressResolver( - private val map: Map>> -) : AdnlAddressResolver { - override suspend fun resolve(address: AdnlIdShort): Pair>? = map[address] -} diff --git a/build.gradle.kts b/build.gradle.kts index 221f9c9f..64393626 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,3 @@ -import org.gradle.internal.impldep.org.bouncycastle.cms.RecipientId.password import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile @@ -12,7 +11,7 @@ plugins { allprojects { group = "org.ton" - version = "0.3.1" + version = "0.4.0-SNAPSHOT" repositories { mavenCentral() diff --git a/contract/src/CellString.kt b/contract/src/CellString.kt index fdf993e7..526ce3d8 100644 --- a/contract/src/CellString.kt +++ b/contract/src/CellString.kt @@ -1,12 +1,11 @@ package org.ton.contract +import kotlinx.io.bytestring.ByteString import org.ton.bitstring.BitString import org.ton.cell.Cell import org.ton.cell.CellBuilder import org.ton.cell.CellSlice import org.ton.cell.storeRef -import org.ton.tl.ByteString -import org.ton.tl.asByteString import org.ton.tlb.TlbConstructor import kotlin.math.min @@ -21,7 +20,7 @@ public object CellStringTlbConstructor : TlbConstructor( forEach(cellSlice, Cell.MAX_BITS_SIZE) { result += it } - return result.toByteArray().asByteString() + return ByteString(*result.toByteArray()) } override fun storeTlb(cellBuilder: CellBuilder, value: ByteString) { @@ -40,9 +39,9 @@ public object CellStringTlbConstructor : TlbConstructor( if (head / 8 == value.size) { cellBuilder.storeBytes(value.toByteArray()) } else { - cellBuilder.storeBytes(value.copyOf(head / 8).toByteArray()) + cellBuilder.storeBytes(value.substring(0, head / 8).toByteArray()) cellBuilder.storeRef { - storeTlb(this, value.copyOfRange(head / 8, value.size)) + storeTlb(this, value.substring(head / 8, value.size)) } } } diff --git a/contract/src/wallet/MessageText.kt b/contract/src/wallet/MessageText.kt index cec72393..b5595e37 100644 --- a/contract/src/wallet/MessageText.kt +++ b/contract/src/wallet/MessageText.kt @@ -1,12 +1,12 @@ package org.ton.contract.wallet +import kotlinx.io.bytestring.ByteString +import kotlinx.io.bytestring.decodeToString import org.ton.api.pk.PrivateKey import org.ton.api.pub.PublicKey import org.ton.cell.CellBuilder import org.ton.cell.CellSlice import org.ton.contract.CellStringTlbConstructor -import org.ton.tl.ByteString -import org.ton.tl.asByteString import org.ton.tlb.TlbCombinator import org.ton.tlb.TlbConstructor import org.ton.tlb.loadTlb @@ -20,7 +20,7 @@ public sealed interface MessageText { ) : MessageText { public fun encrypt(publicKey: PublicKey): Encrypted { val encrypted = publicKey.encrypt(text.encodeToByteArray()) - return Encrypted(encrypted.asByteString()) + return Encrypted(ByteString(*encrypted)) } public companion object : TlbConstructorProvider by TextTlbConstructor @@ -55,7 +55,7 @@ private object TextTlbConstructor : TlbConstructor( } override fun storeTlb(cellBuilder: CellBuilder, value: MessageText.Raw) { - cellBuilder.storeTlb(CellStringTlbConstructor, value.text.encodeToByteArray().asByteString()) + cellBuilder.storeTlb(CellStringTlbConstructor, ByteString(*value.text.encodeToByteArray())) } } diff --git a/contract/src/wallet/WalletV3Contract.kt b/contract/src/wallet/WalletV3Contract.kt index 5ccd0a9a..a58b8ec7 100644 --- a/contract/src/wallet/WalletV3Contract.kt +++ b/contract/src/wallet/WalletV3Contract.kt @@ -1,5 +1,6 @@ package org.ton.contract.wallet +import kotlinx.io.bytestring.ByteString import org.ton.api.pk.PrivateKeyEd25519 import org.ton.api.pub.PublicKeyEd25519 import org.ton.bitstring.BitString @@ -11,7 +12,6 @@ import org.ton.cell.buildCell import org.ton.contract.exception.AccountNotInitializedException import org.ton.contract.wallet.WalletContract.Companion.DEFAULT_WALLET_ID import org.ton.lite.client.LiteClient -import org.ton.tl.asByteString import org.ton.tlb.CellRef import org.ton.tlb.TlbConstructor import org.ton.tlb.constructor.AnyTlbConstructor @@ -72,7 +72,7 @@ public class WalletV3R2Contract( override fun loadTlb(cellSlice: CellSlice): WalletV3R2Data { val seqno = cellSlice.loadUInt(32).toInt() val subWalletId = cellSlice.loadUInt(32).toInt() - val publicKey = PublicKeyEd25519(cellSlice.loadBits(256).toByteArray().asByteString()) + val publicKey = PublicKeyEd25519(ByteString(*cellSlice.loadBits(256).toByteArray())) return WalletV3R2Data(seqno, subWalletId, publicKey) } diff --git a/contract/src/wallet/WalletV4R2Contract.kt b/contract/src/wallet/WalletV4R2Contract.kt index 235c34bd..c4c1441f 100644 --- a/contract/src/wallet/WalletV4R2Contract.kt +++ b/contract/src/wallet/WalletV4R2Contract.kt @@ -1,5 +1,6 @@ package org.ton.contract.wallet +import kotlinx.io.bytestring.ByteString import org.ton.api.pk.PrivateKeyEd25519 import org.ton.api.pub.PublicKeyEd25519 import org.ton.bitstring.BitString @@ -13,7 +14,6 @@ import org.ton.contract.exception.AccountNotInitializedException import org.ton.contract.wallet.WalletContract.Companion.DEFAULT_WALLET_ID import org.ton.hashmap.HashMapE import org.ton.lite.client.LiteClient -import org.ton.tl.asByteString import org.ton.tlb.* import org.ton.tlb.constructor.AnyTlbConstructor import kotlin.io.encoding.Base64 @@ -87,7 +87,7 @@ public class WalletV4R2Contract( override fun loadTlb(cellSlice: CellSlice): Data { val seqno = cellSlice.loadUInt(32).toInt() val subWalletId = cellSlice.loadUInt(32).toInt() - val publicKey = PublicKeyEd25519(cellSlice.loadBits(256).toByteArray().asByteString()) + val publicKey = PublicKeyEd25519(ByteString(*cellSlice.loadBits(256).toByteArray())) val plugins = cellSlice.loadTlb(HashMapE.tlbCodec(8 + 256, AnyTlbConstructor)) return Data(seqno, subWalletId, publicKey, plugins) } diff --git a/libs.versions.toml b/libs.versions.toml index 026a3e37..3a94f313 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -10,6 +10,7 @@ bignum = "0.3.8" # https://search.maven.org/artifact/com.ionspin.kotlin/bignum crypto = "0.0.2" cache4k = "0.12.0" # https://central.sonatype.com/namespace/io.github.reactivecircus.cache4k bcv = "0.13.2" +kotlinx-io = "0.3.1" # https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-io-core/versions [libraries] coroutines-jvm = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8", version.ref = "coroutines" } @@ -22,6 +23,7 @@ benchmark-runtime = { module = "org.jetbrains.kotlinx:kotlinx-benchmark-runtime" serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "serialization" } serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" } serialization-json-jvm = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm", version.ref = "serialization" } +kotlinx-io = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.ref = "kotlinx-io" } ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" } ktor-server-cio = { module = "io.ktor:ktor-server-cio", version.ref = "ktor" } diff --git a/liteapi-tl/src/LiteApiClient.kt b/liteapi-tl/src/LiteApiClient.kt index e0a8c3c6..baf3b83e 100644 --- a/liteapi-tl/src/LiteApiClient.kt +++ b/liteapi-tl/src/LiteApiClient.kt @@ -1,11 +1,11 @@ package org.ton.lite.api -import io.ktor.utils.io.core.* +import kotlinx.io.Buffer +import kotlinx.io.readByteString import org.ton.lite.api.exception.LiteServerException import org.ton.lite.api.liteserver.* import org.ton.lite.api.liteserver.functions.* import org.ton.tl.TlCodec -import org.ton.tl.asByteString public interface LiteApiClient : LiteApi { public suspend fun sendQuery( @@ -14,21 +14,17 @@ public interface LiteApiClient : LiteApi { query: Q, waitMasterchainSeqno: Int = -1 ): A { - val rawQuery = buildPacket { -// println("send query to lite server: $query") + val rawQuery = Buffer().apply { if (waitMasterchainSeqno > 0) { val wait = LiteServerWaitMasterchainSeqno(waitMasterchainSeqno, 30000) -// println("with prefix: $wait") LiteServerWaitMasterchainSeqno.encodeBoxed(this, wait) } queryCodec.encodeBoxed(this, query) - }.readBytes() - val liteServerQuery = LiteServerQuery(rawQuery.asByteString()) - val result = sendRawQuery(buildPacket { - LiteServerQuery.encodeBoxed(this, liteServerQuery) - }) + }.readByteString() + val liteServerQuery = LiteServerQuery(rawQuery) + val result = sendRawQuery(LiteServerQuery.encodeToByteArray(liteServerQuery, true)) val liteServerError = try { - LiteServerError.decodeBoxed(result.copy()) + LiteServerError.decodeBoxed(result) } catch (e: Exception) { null } @@ -39,7 +35,7 @@ public interface LiteApiClient : LiteApi { return answer } - public suspend fun sendRawQuery(query: ByteReadPacket): ByteReadPacket + public suspend fun sendRawQuery(query: ByteArray): ByteArray override suspend fun invoke( function: LiteServerGetMasterchainInfo, diff --git a/liteapi-tl/src/liteserver/LiteServerAccountId.kt b/liteapi-tl/src/liteserver/LiteServerAccountId.kt index c2a5b768..ea1eaf06 100644 --- a/liteapi-tl/src/liteserver/LiteServerAccountId.kt +++ b/liteapi-tl/src/liteserver/LiteServerAccountId.kt @@ -2,13 +2,12 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers -import org.ton.bitstring.BitString import org.ton.crypto.HexByteArraySerializer -import org.ton.tl.ByteString -import org.ton.tl.ByteString.Companion.toByteString +import org.ton.tl.ByteStringBase64Serializer import org.ton.tl.TlConstructor import org.ton.tl.TlReader import org.ton.tl.TlWriter @@ -21,23 +20,21 @@ public data class LiteServerAccountId( val workchain: Int, @get:JvmName("id") + @Serializable(ByteStringBase64Serializer::class) val id: ByteString ) { - public constructor(workchain: Int, id: ByteArray) : this(workchain, id.toByteString()) - public constructor(workchain: Int, id: BitString) : this(workchain, id.toByteArray()) - public companion object : TlConstructor( schema = "liteServer.accountId workchain:int id:int256 = liteServer.AccountId" ) { override fun decode(reader: TlReader): LiteServerAccountId { val workchain = reader.readInt() - val id = reader.readRaw(32) + val id = reader.readByteString(32) return LiteServerAccountId(workchain, id) } override fun encode(writer: TlWriter, value: LiteServerAccountId) { writer.writeInt(value.workchain) - writer.writeRaw(value.id.toByteArray()) + writer.writeRaw(value.id) } } } diff --git a/liteapi-tl/src/liteserver/LiteServerAccountState.kt b/liteapi-tl/src/liteserver/LiteServerAccountState.kt index 976eeadf..4982d5b6 100644 --- a/liteapi-tl/src/liteserver/LiteServerAccountState.kt +++ b/liteapi-tl/src/liteserver/LiteServerAccountState.kt @@ -2,6 +2,7 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -22,12 +23,15 @@ public data class LiteServerAccountState( @SerialName("shard_proof") @get:JvmName("shardProof") + @Serializable(ByteStringBase64Serializer::class) val shardProof: ByteString, @get:JvmName("proof") + @Serializable(ByteStringBase64Serializer::class) val proof: ByteString, @get:JvmName("state") + @Serializable(ByteStringBase64Serializer::class) val state: ByteString ) { public companion object : TlConstructor( diff --git a/liteapi-tl/src/liteserver/LiteServerAllShardsInfo.kt b/liteapi-tl/src/liteserver/LiteServerAllShardsInfo.kt index fcba96af..366c7675 100644 --- a/liteapi-tl/src/liteserver/LiteServerAllShardsInfo.kt +++ b/liteapi-tl/src/liteserver/LiteServerAllShardsInfo.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -13,9 +14,11 @@ public data class LiteServerAllShardsInfo( val id: TonNodeBlockIdExt, @get:JvmName("proof") + @Serializable(ByteStringBase64Serializer::class) val proof: ByteString, @get:JvmName("data") + @Serializable(ByteStringBase64Serializer::class) val data: ByteString ) { public companion object : TlCodec by LiteServerAllShardsInfoTlConstructor diff --git a/liteapi-tl/src/liteserver/LiteServerBlockData.kt b/liteapi-tl/src/liteserver/LiteServerBlockData.kt index b3e2d778..73d8680d 100644 --- a/liteapi-tl/src/liteserver/LiteServerBlockData.kt +++ b/liteapi-tl/src/liteserver/LiteServerBlockData.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -13,6 +14,7 @@ public class LiteServerBlockData( public val id: TonNodeBlockIdExt, @get:JvmName("data") + @Serializable(ByteStringBase64Serializer::class) public val data: ByteString ) { public companion object : TlConstructor( diff --git a/liteapi-tl/src/liteserver/LiteServerBlockHeader.kt b/liteapi-tl/src/liteserver/LiteServerBlockHeader.kt index c423b45e..12e4e2d8 100644 --- a/liteapi-tl/src/liteserver/LiteServerBlockHeader.kt +++ b/liteapi-tl/src/liteserver/LiteServerBlockHeader.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -17,6 +18,7 @@ public data class LiteServerBlockHeader( @SerialName("header_proof") @get:JvmName("headerProof") + @Serializable(ByteStringBase64Serializer::class) val headerProof: ByteString ) { public companion object : TlCodec by LiteServerBlockHeaderTlConstructor diff --git a/liteapi-tl/src/liteserver/LiteServerBlockLinkBack.kt b/liteapi-tl/src/liteserver/LiteServerBlockLinkBack.kt index a15f3ab8..2436163e 100644 --- a/liteapi-tl/src/liteserver/LiteServerBlockLinkBack.kt +++ b/liteapi-tl/src/liteserver/LiteServerBlockLinkBack.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -22,13 +23,16 @@ public data class LiteServerBlockLinkBack( @SerialName("dest_proof") @get:JvmName("destProof") + @Serializable(ByteStringBase64Serializer::class) val destProof: ByteString, @get:JvmName("proof") + @Serializable(ByteStringBase64Serializer::class) val proof: ByteString, @SerialName("state_proof") @get:JvmName("stateProof") + @Serializable(ByteStringBase64Serializer::class) val stateProof: ByteString ) : LiteServerBlockLink { diff --git a/liteapi-tl/src/liteserver/LiteServerBlockLinkForward.kt b/liteapi-tl/src/liteserver/LiteServerBlockLinkForward.kt index 3d8780f8..d0b4bd7d 100644 --- a/liteapi-tl/src/liteserver/LiteServerBlockLinkForward.kt +++ b/liteapi-tl/src/liteserver/LiteServerBlockLinkForward.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -22,10 +23,12 @@ public data class LiteServerBlockLinkForward( @SerialName("dest_proof") @get:JvmName("destProof") + @Serializable(ByteStringBase64Serializer::class) val destProof: ByteString, @SerialName("config_proof") @get:JvmName("configProof") + @Serializable(ByteStringBase64Serializer::class) val configProof: ByteString, @get:JvmName("signatures") diff --git a/liteapi-tl/src/liteserver/LiteServerBlockState.kt b/liteapi-tl/src/liteserver/LiteServerBlockState.kt index 493b4933..1b526ca9 100644 --- a/liteapi-tl/src/liteserver/LiteServerBlockState.kt +++ b/liteapi-tl/src/liteserver/LiteServerBlockState.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -14,13 +15,16 @@ public data class LiteServerBlockState( @SerialName("root_hash") @get:JvmName("rootHash") + @Serializable(ByteStringBase64Serializer::class) val rootHash: ByteString, @SerialName("file_hash") @get:JvmName("fileHash") + @Serializable(ByteStringBase64Serializer::class) val fileHash: ByteString, @get:JvmName("data") + @Serializable(ByteStringBase64Serializer::class) val data: ByteString ) { init { diff --git a/liteapi-tl/src/liteserver/LiteServerBlockTransactions.kt b/liteapi-tl/src/liteserver/LiteServerBlockTransactions.kt index 102b3c4a..5c2702e8 100644 --- a/liteapi-tl/src/liteserver/LiteServerBlockTransactions.kt +++ b/liteapi-tl/src/liteserver/LiteServerBlockTransactions.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -23,6 +24,7 @@ public data class LiteServerBlockTransactions( val ids: List, @get:JvmName("proof") + @Serializable(ByteStringBase64Serializer::class) val proof: ByteString ) { public companion object : TlCodec by LiteServerBlockTransactionsTlConstructor diff --git a/liteapi-tl/src/liteserver/LiteServerConfigInfo.kt b/liteapi-tl/src/liteserver/LiteServerConfigInfo.kt index e08d1d4a..5a0a6dfc 100644 --- a/liteapi-tl/src/liteserver/LiteServerConfigInfo.kt +++ b/liteapi-tl/src/liteserver/LiteServerConfigInfo.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -16,9 +17,11 @@ public data class LiteServerConfigInfo( val id: TonNodeBlockIdExt, @get:JvmName("stateProof") + @Serializable(ByteStringBase64Serializer::class) val stateProof: ByteString, @get:JvmName("configProof") + @Serializable(ByteStringBase64Serializer::class) val configProof: ByteString ) { public companion object : TlCodec by LiteServerConfigInfoTlConstructor diff --git a/liteapi-tl/src/liteserver/LiteServerMasterchainInfo.kt b/liteapi-tl/src/liteserver/LiteServerMasterchainInfo.kt index 9420d1ad..87174f2e 100644 --- a/liteapi-tl/src/liteserver/LiteServerMasterchainInfo.kt +++ b/liteapi-tl/src/liteserver/LiteServerMasterchainInfo.kt @@ -3,6 +3,7 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -19,6 +20,7 @@ public data class LiteServerMasterchainInfo( public val last: TonNodeBlockIdExt, @get:JvmName("stateRootHash") + @Serializable(ByteStringBase64Serializer::class) public val stateRootHash: ByteString, @get:JvmName("init") diff --git a/liteapi-tl/src/liteserver/LiteServerMasterchainInfoExt.kt b/liteapi-tl/src/liteserver/LiteServerMasterchainInfoExt.kt index bee30c5f..690ddc8d 100644 --- a/liteapi-tl/src/liteserver/LiteServerMasterchainInfoExt.kt +++ b/liteapi-tl/src/liteserver/LiteServerMasterchainInfoExt.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -31,6 +32,7 @@ public data class LiteServerMasterchainInfoExt( @SerialName("state_root_hash") @get:JvmName("stateRootHash") + @Serializable(ByteStringBase64Serializer::class) val stateRootHash: ByteString, @get:JvmName("init") diff --git a/liteapi-tl/src/liteserver/LiteServerRunMethodResult.kt b/liteapi-tl/src/liteserver/LiteServerRunMethodResult.kt index 601cf9f9..307de0d7 100644 --- a/liteapi-tl/src/liteserver/LiteServerRunMethodResult.kt +++ b/liteapi-tl/src/liteserver/LiteServerRunMethodResult.kt @@ -1,10 +1,10 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -23,21 +23,26 @@ public data class LiteServerRunMethodResult internal constructor( @SerialName("shard_proof") @get:JvmName("shardProof") + @Serializable(ByteStringBase64Serializer::class) val shardProof: ByteString?, @get:JvmName("proof") + @Serializable(ByteStringBase64Serializer::class) val proof: ByteString?, @SerialName("state_proof") @get:JvmName("stateProof") + @Serializable(ByteStringBase64Serializer::class) val stateProof: ByteString?, @SerialName("init_c7") @get:JvmName("initC7") + @Serializable(ByteStringBase64Serializer::class) val initC7: ByteString?, @SerialName("lib_extras") @get:JvmName("libExtras") + @Serializable(ByteStringBase64Serializer::class) val libExtras: ByteString?, @SerialName("exit_code") @@ -45,37 +50,9 @@ public data class LiteServerRunMethodResult internal constructor( val exitCode: Int, @get:JvmName("result") + @Serializable(ByteStringBase64Serializer::class) val result: ByteString? ) { - public constructor( - id: TonNodeBlockIdExt, - shardBlock: TonNodeBlockIdExt, - shardProof: ByteArray?, - proof: ByteArray?, - stateProof: ByteArray?, - initC7: ByteArray?, - libExtras: ByteArray?, - exitCode: Int, - result: ByteArray? - ) : this( - mode( - shardProof != null, - stateProof != null, - result != null, - initC7 != null, - libExtras != null, - ), - id, - shardBlock, - shardProof?.toByteString(), - proof?.toByteString(), - stateProof?.toByteString(), - initC7?.toByteString(), - libExtras?.toByteString(), - exitCode, - result?.toByteString() - ) - public companion object : TlCodec by LiteServerRunMethodResultTlConstructor { @JvmStatic public fun mode( diff --git a/liteapi-tl/src/liteserver/LiteServerShardInfo.kt b/liteapi-tl/src/liteserver/LiteServerShardInfo.kt index 0010cd36..9593c7a1 100644 --- a/liteapi-tl/src/liteserver/LiteServerShardInfo.kt +++ b/liteapi-tl/src/liteserver/LiteServerShardInfo.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -18,10 +19,12 @@ public data class LiteServerShardInfo( @SerialName("shard_proof") @get:JvmName("shardProof") + @Serializable(ByteStringBase64Serializer::class) val shardProof: ByteString, @SerialName("shard_descr") @get:JvmName("shardDescr") + @Serializable(ByteStringBase64Serializer::class) val shardDescr: ByteString ) { public companion object : TlCodec by LiteServerShardInfoTlConstructor diff --git a/liteapi-tl/src/liteserver/LiteServerSignature.kt b/liteapi-tl/src/liteserver/LiteServerSignature.kt index 17e53da5..21ae30dc 100644 --- a/liteapi-tl/src/liteserver/LiteServerSignature.kt +++ b/liteapi-tl/src/liteserver/LiteServerSignature.kt @@ -1,9 +1,9 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString import kotlin.jvm.JvmName @Serializable @@ -11,13 +11,13 @@ import kotlin.jvm.JvmName public data class LiteServerSignature( @SerialName("node_id_short") @get:JvmName("nodeIdShort") + @Serializable(ByteStringBase64Serializer::class) val nodeIdShort: ByteString, @get:JvmName("signature") + @Serializable(ByteStringBase64Serializer::class) val signature: ByteString ) { - public constructor(nodeIdShort: ByteArray, signature: ByteArray) : this(nodeIdShort.toByteString(), signature.toByteString()) - public companion object : TlCodec by LiteServerSignatureTlConstructor } diff --git a/liteapi-tl/src/liteserver/LiteServerTransactionId.kt b/liteapi-tl/src/liteserver/LiteServerTransactionId.kt index 9b9def9f..ddc7ad3d 100644 --- a/liteapi-tl/src/liteserver/LiteServerTransactionId.kt +++ b/liteapi-tl/src/liteserver/LiteServerTransactionId.kt @@ -1,23 +1,21 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString import kotlin.jvm.JvmStatic @Serializable @SerialName("liteServer.transactionId") public data class LiteServerTransactionId internal constructor( val mode: Int, + @Serializable(ByteStringBase64Serializer::class) val account: ByteString?, val lt: Long?, + @Serializable(ByteStringBase64Serializer::class) val hash: ByteString? ) { - public constructor(account: ByteArray?, lt: Long?, hash: ByteArray?) : this( - mode(account != null, lt != null, hash != null), account?.toByteString(), lt, hash?.toByteString() - ) - init { require(account == null || account.size == 32) { "account must be 32 bytes long" } require(hash == null || hash.size == 32) { "hash must be 32 bytes long" } diff --git a/liteapi-tl/src/liteserver/LiteServerTransactionId3.kt b/liteapi-tl/src/liteserver/LiteServerTransactionId3.kt index 300b8317..2e0d0078 100644 --- a/liteapi-tl/src/liteserver/LiteServerTransactionId3.kt +++ b/liteapi-tl/src/liteserver/LiteServerTransactionId3.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.tl.* @@ -9,6 +10,7 @@ import kotlin.jvm.JvmName @SerialName("liteServer.transactionId3") public data class LiteServerTransactionId3( @get:JvmName("account") + @Serializable(ByteStringBase64Serializer::class) val account: ByteString, @get:JvmName("lt") diff --git a/liteapi-tl/src/liteserver/LiteServerTransactionInfo.kt b/liteapi-tl/src/liteserver/LiteServerTransactionInfo.kt index 2d083789..7a61c5eb 100644 --- a/liteapi-tl/src/liteserver/LiteServerTransactionInfo.kt +++ b/liteapi-tl/src/liteserver/LiteServerTransactionInfo.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -13,9 +14,11 @@ public data class LiteServerTransactionInfo( val id: TonNodeBlockIdExt, @get:JvmName("proof") + @Serializable(ByteStringBase64Serializer::class) val proof: ByteString, @get:JvmName("transaction") + @Serializable(ByteStringBase64Serializer::class) val transaction: ByteString ) { public companion object : TlCodec by LiteServerTransactionInfoTlConstructor diff --git a/liteapi-tl/src/liteserver/LiteServerTransactionList.kt b/liteapi-tl/src/liteserver/LiteServerTransactionList.kt index 42c72513..fb61a443 100644 --- a/liteapi-tl/src/liteserver/LiteServerTransactionList.kt +++ b/liteapi-tl/src/liteserver/LiteServerTransactionList.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -13,6 +14,7 @@ public data class LiteServerTransactionList( val ids: List, @get:JvmName("transactions") + @Serializable(ByteStringBase64Serializer::class) val transactions: ByteString ) { public companion object : TlCodec by LiteServerTransactionListTlConstructor diff --git a/liteapi-tl/src/liteserver/LiteServerValidatorStats.kt b/liteapi-tl/src/liteserver/LiteServerValidatorStats.kt index f80908f6..0bfab5e1 100644 --- a/liteapi-tl/src/liteserver/LiteServerValidatorStats.kt +++ b/liteapi-tl/src/liteserver/LiteServerValidatorStats.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -23,10 +24,12 @@ public data class LiteServerValidatorStats( @SerialName("state_proof") @get:JvmName("stateProof") + @Serializable(ByteStringBase64Serializer::class) val stateProof: ByteString, @SerialName("data_proof") @get:JvmName("dataProof") + @Serializable(ByteStringBase64Serializer::class) val dataProof: ByteString ) { public companion object : TlCodec by LiteServerValidatorStatsTlConstructor diff --git a/liteapi-tl/src/liteserver/functions/LiteServerGetTransactions.kt b/liteapi-tl/src/liteserver/functions/LiteServerGetTransactions.kt index f2225b15..cc823db4 100644 --- a/liteapi-tl/src/liteserver/functions/LiteServerGetTransactions.kt +++ b/liteapi-tl/src/liteserver/functions/LiteServerGetTransactions.kt @@ -2,6 +2,7 @@ package org.ton.lite.api.liteserver.functions +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -9,7 +10,6 @@ import org.ton.crypto.HexByteArraySerializer import org.ton.lite.api.liteserver.LiteServerAccountId import org.ton.lite.api.liteserver.LiteServerTransactionList import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString import kotlin.jvm.JvmName @Serializable @@ -25,12 +25,9 @@ public data class LiteServerGetTransactions( val lt: Long, @get:JvmName("hash") + @Serializable(ByteStringBase64Serializer::class) val hash: ByteString ) : TLFunction { - public constructor(count: Int, account: LiteServerAccountId, lt: Long, hash: ByteArray) : this( - count, account, lt, hash.toByteString() - ) - init { require(hash.size == 32) } diff --git a/liteapi-tl/src/liteserver/functions/LiteServerGetValidatorStats.kt b/liteapi-tl/src/liteserver/functions/LiteServerGetValidatorStats.kt index 4ebc0741..d11dec16 100644 --- a/liteapi-tl/src/liteserver/functions/LiteServerGetValidatorStats.kt +++ b/liteapi-tl/src/liteserver/functions/LiteServerGetValidatorStats.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver.functions +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -20,6 +21,7 @@ public data class LiteServerGetValidatorStats( val limit: Int, @get:JvmName("startAfter") + @Serializable(ByteStringBase64Serializer::class) val startAfter: ByteString?, @get:JvmName("modifiedAfter") diff --git a/liteapi-tl/src/liteserver/functions/LiteServerQuery.kt b/liteapi-tl/src/liteserver/functions/LiteServerQuery.kt index 0ace754e..2f815a7f 100644 --- a/liteapi-tl/src/liteserver/functions/LiteServerQuery.kt +++ b/liteapi-tl/src/liteserver/functions/LiteServerQuery.kt @@ -2,6 +2,7 @@ package org.ton.lite.api.liteserver.functions +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -13,6 +14,7 @@ import kotlin.jvm.JvmName @SerialName("liteServer.query") public data class LiteServerQuery( @get:JvmName("data") + @Serializable(ByteStringBase64Serializer::class) val data: ByteString ) { public companion object : TlCodec by LiteServerQueryTlConstructor diff --git a/liteapi-tl/src/liteserver/functions/LiteServerRunSmcMethod.kt b/liteapi-tl/src/liteserver/functions/LiteServerRunSmcMethod.kt index e17bdd86..5c0518b5 100644 --- a/liteapi-tl/src/liteserver/functions/LiteServerRunSmcMethod.kt +++ b/liteapi-tl/src/liteserver/functions/LiteServerRunSmcMethod.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver.functions +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockIdExt @@ -31,6 +32,7 @@ public data class LiteServerRunSmcMethod( val methodId: Long, @get:JvmName("params") + @Serializable(ByteStringBase64Serializer::class) val params: ByteString ) : TLFunction { override fun tlCodec(): TlCodec = LiteServerRunSmcMethod diff --git a/liteapi-tl/src/liteserver/functions/LiteServerSendMessage.kt b/liteapi-tl/src/liteserver/functions/LiteServerSendMessage.kt index 091666c0..9fbc14a0 100644 --- a/liteapi-tl/src/liteserver/functions/LiteServerSendMessage.kt +++ b/liteapi-tl/src/liteserver/functions/LiteServerSendMessage.kt @@ -1,5 +1,6 @@ package org.ton.lite.api.liteserver.functions +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.lite.api.liteserver.LiteServerSendMsgStatus @@ -10,6 +11,7 @@ import kotlin.jvm.JvmName @SerialName("liteServer.sendMessage") public data class LiteServerSendMessage( @get:JvmName("body") + @Serializable(ByteStringBase64Serializer::class) val body: ByteString ) : TLFunction { override fun tlCodec(): TlCodec = LiteServerSendMessageTlConstructor diff --git a/liteclient/src/LiteClient.kt b/liteclient/src/LiteClient.kt index 846d38db..709460d0 100644 --- a/liteclient/src/LiteClient.kt +++ b/liteclient/src/LiteClient.kt @@ -1,10 +1,13 @@ package org.ton.lite.client +import io.github.andreypfau.kotlinx.crypto.sha2.sha256 import io.ktor.utils.io.core.* import kotlinx.atomicfu.atomic import kotlinx.coroutines.* import kotlinx.datetime.Clock import kotlinx.datetime.Instant +import kotlinx.io.bytestring.ByteString +import kotlinx.io.bytestring.contentEquals import org.ton.adnl.connection.AdnlClientImpl import org.ton.api.exception.TonNotReadyException import org.ton.api.exception.TvmException @@ -27,8 +30,6 @@ import org.ton.lite.api.liteserver.functions.* import org.ton.lite.client.internal.FullAccountState import org.ton.lite.client.internal.TransactionId import org.ton.lite.client.internal.TransactionInfo -import org.ton.tl.ByteReadPacket -import org.ton.tl.asByteString import org.ton.tlb.CellRef import org.ton.tlb.constructor.AnyTlbConstructor import org.ton.tlb.storeTlb @@ -76,16 +77,15 @@ public class LiteClient( private var currentServer: Int = 0 public val liteApi: LiteApiClient = object : LiteApiClient { - override suspend fun sendRawQuery(query: ByteReadPacket): ByteReadPacket { + override suspend fun sendRawQuery(query: ByteArray): ByteArray { var attempts = 0 var exception: Exception? = null var liteServer: LiteServerDesc? = null - val bytes = query.readBytes() while (attempts < maxOf(5, serverList.size)) { try { liteServer = serverList[currentServer++ % serverList.size] val client = AdnlClientImpl(liteServer) - return client.sendQuery(ByteReadPacket(bytes), 10.seconds) + return client.sendQuery(query, 10.seconds) } catch (e: LiteServerException) { exception = e break @@ -267,7 +267,7 @@ public class LiteClient( "block id mismatch, expected: $blockId actual: $actualBlockId" } val blockProofCell = try { - BagOfCells.read(ByteReadPacket(blockHeader.headerProof)).first() + BagOfCells.of(blockHeader.headerProof.toByteArray()).first() } catch (e: Exception) { throw IllegalStateException("Can't parse block proof", e) } @@ -308,13 +308,13 @@ public class LiteClient( } catch (e: Exception) { throw RuntimeException("Can't get block $blockId from server", e) } - val actualFileHash = blockData.data.hashSha256() - check(blockId.fileHash == actualFileHash) { + val actualFileHash = sha256(blockData.data.toByteArray()) + check(blockId.fileHash.contentEquals(actualFileHash)) { "file hash mismatch for block $blockId, expected: ${blockId.fileHash} , actual: $actualFileHash" } registerBlockId(blockId) val root = try { - BagOfCells.read(ByteReadPacket(blockData.data)).first() + BagOfCells.of(blockData.data.toByteArray()).first() } catch (e: Exception) { throw RuntimeException("Can't deserialize block data", e) } @@ -375,10 +375,10 @@ public class LiteClient( count, accountAddress.toLiteServer(), fromTransactionId.lt, - fromTransactionId.hash.toByteArray() + ByteString(*fromTransactionId.hash.toByteArray()) ) ) - val transactionsCells = BagOfCells.read(ByteReadPacket(rawTransactionList.transactions)).roots + val transactionsCells = BagOfCells.of(rawTransactionList.transactions.toByteArray()).roots check(rawTransactionList.ids.size == transactionsCells.size) return List(transactionsCells.size) { index -> val transaction = CellRef(transactionsCells[index], Transaction) @@ -434,14 +434,14 @@ public class LiteClient( // logger.debug { "run: $address - ${params.toList()}" } val result = liteApi( LiteServerRunSmcMethod( - 0b100, blockId, address, method, smcCreateParams(params).toByteArray().asByteString() + 0b100, blockId, address, method, ByteString(*smcCreateParams(params).toByteArray()) ) ) check((!blockId.isValid()) || blockId == result.id) { "block id mismatch, expected: $blockId actual: $result.id" } - val boc = BagOfCells.read( - ByteReadPacket(checkNotNull(result.result) { "result is null, but 0b100 mode provided" }) + val boc = BagOfCells.of( + checkNotNull(result.result) { "result is null, but 0b100 mode provided" }.toByteArray() ) // TODO: check proofs val exitCode = result.exitCode @@ -460,7 +460,7 @@ public class LiteClient( public suspend fun sendMessage(cell: Cell): LiteServerSendMsgStatus = sendMessage(BagOfCells(cell)) public suspend fun sendMessage(boc: BagOfCells): LiteServerSendMsgStatus { - return liteApi(LiteServerSendMessage(boc.toByteArray().asByteString())) + return liteApi(LiteServerSendMessage(ByteString(*boc.toByteArray()))) } private fun smcMethodId(methodName: String): Long = crc16(methodName).toLong() or 0x10000 @@ -503,5 +503,5 @@ public class LiteClient( knownBlockIds.addLast(blockIdExt) } - private fun MsgAddressInt.toLiteServer() = LiteServerAccountId(workchainId, address.toByteArray()) + private fun MsgAddressInt.toLiteServer() = LiteServerAccountId(workchainId, ByteString(*address.toByteArray())) } diff --git a/tl/build.gradle.kts b/tl/build.gradle.kts index 56c22e3d..1015de63 100644 --- a/tl/build.gradle.kts +++ b/tl/build.gradle.kts @@ -11,6 +11,7 @@ kotlin { api(projects.tonKotlinBitstring) api(libs.ktor.utils) api(libs.serialization.json) + api(libs.kotlinx.io) } } } diff --git a/tl/src/ByteString.kt b/tl/src/ByteString.kt deleted file mode 100644 index 1ab0e32f..00000000 --- a/tl/src/ByteString.kt +++ /dev/null @@ -1,159 +0,0 @@ -package org.ton.tl - -import io.ktor.util.* -import io.ktor.utils.io.core.* -import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.descriptors.PrimitiveKind -import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder -import kotlin.experimental.and -import kotlin.io.encoding.Base64 -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic - -@Serializable(ByteStringSerializer::class) -//@Deprecated("Use ByteString from kotlinx-io") -public open class ByteString internal constructor( - internal val data: ByteArray -) : Comparable, Collection { - private val hashCode by lazy(LazyThreadSafetyMode.PUBLICATION) { - data.contentHashCode() - } - - public override val size: Int get() = data.size - - override fun containsAll(elements: Collection): Boolean = - elements.all { contains(it) } - - override fun contains(element: Byte): Boolean = - data.contains(element) - - @JvmName("getByte") - public operator fun get(index: Int): Byte = data[index] - - public fun toByteArray(): ByteArray = data.copyOf() - - public fun toByteArray( - destination: ByteArray, - destinationOffset: Int = 0, - startIndex: Int = 0, - endIndex: Int = size - ): ByteArray = - data.copyInto(destination, destinationOffset, startIndex, endIndex) - - public fun copyOf(newSize: Int): ByteString = ByteString(data.copyOf(newSize)) - - public fun copyOfRange(fromIndex: Int, toIndex: Int): ByteString = ByteString(data.copyOfRange(fromIndex, toIndex)) - - public fun copyInto( - destination: ByteArray, - destinationOffset: Int = 0, - startIndex: Int = 0, - endIndex: Int = size - ): ByteArray = - data.copyInto(destination, destinationOffset, startIndex, endIndex) - - public fun encodeHex(): String = data.toHexString().uppercase() - - public fun encodeBase64(): String = Base64.encode(data) - - public fun decodeToString(): String = data.decodeToString() - - public fun hashSha256(): ByteString = io.github.andreypfau.kotlinx.crypto.sha2.sha256(data).asByteString() - - override fun isEmpty(): Boolean = data.isEmpty() - - override fun compareTo(other: ByteString): Int { - val sizeA = size - val sizeB = other.size - var i = 0 - val size = minOf(sizeA, sizeB) - while (i < size) { - val byteA = this[i] and 0xff.toByte() - val byteB = other[i] and 0xff.toByte() - if (byteA == byteB) { - i++ - continue - } - return if (byteA < byteB) -1 else 1 - } - if (sizeA == sizeB) return 0 - return if (sizeA < sizeB) -1 else 1 - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is ByteString) return false - return data.contentEquals(other.data) - } - - override fun hashCode(): Int = hashCode - - override fun iterator(): ByteIterator = ByteIteratorImpl(data) - - override fun toString(): String = "0x${encodeHex().uppercase()}" - - private class ByteIteratorImpl(val collection: ByteArray) : ByteIterator() { - var index: Int = 0 - - override fun nextByte(): Byte { - if (!hasNext()) throw NoSuchElementException("$index") - return collection[index++] - } - - override operator fun hasNext(): Boolean { - return index < collection.size - } - } - - public companion object { - @JvmStatic - public fun of(vararg bytes: Byte): ByteString = ByteString(bytes) - - @JvmStatic - @JvmName("of") - public fun ByteArray.toByteString(fromIndex: Int = 0, toIndex: Int = size): ByteString = - ByteString(copyOfRange(fromIndex, toIndex)) - - @JvmStatic - public fun String.decodeFromHex(): ByteString = ByteString(hex(this)) - - @JvmStatic - public fun String.decodeFromBase64(): ByteString = ByteString(Base64.decode(this)) - } -} - -public fun ByteArray.asByteString(): ByteString = ByteString(this) - -public fun Output.writeByteString(value: ByteString, offset: Int = 0, length: Int = value.size - offset) { - writeFully(value.data, offset, length) -} - -public fun Input.readByteString(size: Int): ByteString { - val data = ByteArray(size) - readFully(data) - return ByteString(data) -} - -public fun ByteReadPacket( - src: ByteString, - offset: Int = 0, - length: Int = src.size - offset, - block: (ByteArray) -> Unit = {} -): ByteReadPacket = ByteReadPacket(src.data, offset, length, block) - -public object ByteStringSerializer : KSerializer { - override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("ByteString", PrimitiveKind.STRING) - - override fun deserialize(decoder: Decoder): ByteString { - return ByteString(decoder.decodeString().decodeBase64Bytes()) - } - - override fun serialize(encoder: Encoder, value: ByteString) { - encoder.encodeString(value.data.encodeBase64()) - } -} diff --git a/tl/src/ByteStringBase64Serializer.kt b/tl/src/ByteStringBase64Serializer.kt new file mode 100644 index 00000000..82635234 --- /dev/null +++ b/tl/src/ByteStringBase64Serializer.kt @@ -0,0 +1,24 @@ +package org.ton.tl + +import kotlinx.io.bytestring.ByteString +import kotlinx.io.bytestring.decodeToByteString +import kotlinx.io.bytestring.encode +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlin.io.encoding.Base64 + +public object ByteStringBase64Serializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ByteString", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): ByteString { + return Base64.decodeToByteString(decoder.decodeString()) + } + + override fun serialize(encoder: Encoder, value: ByteString) { + encoder.encodeString(Base64.encode(value)) + } +} diff --git a/tl/src/TlDecoder.kt b/tl/src/TlDecoder.kt index 1e114080..ebcde2bd 100644 --- a/tl/src/TlDecoder.kt +++ b/tl/src/TlDecoder.kt @@ -1,15 +1,30 @@ package org.ton.tl -import io.ktor.utils.io.core.* +import kotlinx.io.Buffer +import kotlinx.io.Source +import kotlinx.io.bytestring.ByteString +import kotlinx.io.write public interface TlDecoder { - public fun decode(byteArray: ByteArray): T = decode(ByteReadPacket(byteArray)) - public fun decode(byteString: ByteString): T = decode(ByteReadPacket(byteString)) - public fun decode(input: Input): T = decode(TlReader(input)) + public fun decode(byteArray: ByteArray): T = decode(Buffer().also { + it.write(byteArray) + }) + + public fun decode(byteString: ByteString): T = decode(Buffer().also { + it.write(byteString) + }) + + public fun decode(source: Source): T = decode(TlReader(source)) public fun decode(reader: TlReader): T - public fun decodeBoxed(byteArray: ByteArray): T = decodeBoxed(ByteReadPacket(byteArray)) - public fun decodeBoxed(byteString: ByteString): T = decodeBoxed(ByteReadPacket(byteString)) - public fun decodeBoxed(input: Input): T = decodeBoxed(TlReader(input)) + public fun decodeBoxed(byteArray: ByteArray): T = decodeBoxed(Buffer().also { + it.write(byteArray) + }) + + public fun decodeBoxed(byteString: ByteString): T = decodeBoxed(Buffer().also { + it.write(byteString) + }) + + public fun decodeBoxed(source: Source): T = decodeBoxed(TlReader(source)) public fun decodeBoxed(reader: TlReader): T } diff --git a/tl/src/TlEncoder.kt b/tl/src/TlEncoder.kt index 08d74d97..211062fc 100644 --- a/tl/src/TlEncoder.kt +++ b/tl/src/TlEncoder.kt @@ -1,21 +1,24 @@ package org.ton.tl -import io.ktor.utils.io.core.* +import kotlinx.io.Buffer +import kotlinx.io.Sink +import kotlinx.io.bytestring.ByteString +import kotlinx.io.readByteArray public interface TlEncoder { - public fun encode(output: Output, value: T): Unit = encode(TlWriter(output), value) + public fun encode(sink: Sink, value: T): Unit = encode(TlWriter(sink), value) public fun encode(writer: TlWriter, value: T) - public fun encodeBoxed(output: Output, value: T): Unit = encodeBoxed(TlWriter(output), value) + public fun encodeBoxed(sink: Sink, value: T): Unit = encodeBoxed(TlWriter(sink), value) public fun encodeBoxed(writer: TlWriter, value: T) public fun encodeToByteArray(value: T, boxed: Boolean = true): ByteArray { - val output = BytePacketBuilder() - if (boxed) encodeBoxed(output, value) else encode(output, value) - return output.build().readBytes() + val buffer = Buffer() + if (boxed) encodeBoxed(buffer, value) else encode(buffer, value) + return buffer.readByteArray() } public fun encodeToByteString(value: T, boxed: Boolean = true): ByteString = - ByteString.of(*encodeToByteArray(value, boxed)) + ByteString(*encodeToByteArray(value, boxed)) public fun hash(value: T): ByteArray = io.github.andreypfau.kotlinx.crypto.sha2.sha256(encodeToByteArray(value)) diff --git a/tl/src/TlReader.kt b/tl/src/TlReader.kt index 82078562..754a0d24 100644 --- a/tl/src/TlReader.kt +++ b/tl/src/TlReader.kt @@ -1,22 +1,23 @@ package org.ton.tl -import io.ktor.utils.io.core.* +import kotlinx.io.* +import kotlinx.io.bytestring.ByteString import org.ton.tl.constructors.BoolTlCombinator public class TlReader( - public val input: Input + public val input: Source ) { public fun readBoolean(): Boolean = BoolTlCombinator.decode(this).value - public fun readInt(): Int = input.readIntLittleEndian() - public fun readLong(): Long = input.readLongLittleEndian() - public fun readRaw(size: Int): ByteArray = input.readBytes(size) + public fun readInt(): Int = input.readIntLe() + public fun readLong(): Long = input.readLongLe() + public fun readRaw(size: Int): ByteArray = input.readByteArray(size) public fun readByteString(size: Int): ByteString { - return ByteString(input.readBytes(size)) + return input.readByteString(size) } public fun readByteString(): ByteString { - return ByteString(readBytes()) + return ByteString(*readBytes()) } public fun readBytes(): ByteArray { @@ -43,7 +44,7 @@ public class TlReader( resultLength = resultLengthLong.toInt() resultAlignedLength = resultLength + 8 } - val result = input.readBytes(resultLength) + val result = input.readByteArray(resultLength) while (resultAlignedLength++ % 4 > 0) { check(input.readByte() == 0.toByte()) } diff --git a/tl/src/TlWriter.kt b/tl/src/TlWriter.kt index 03658697..001f29ac 100644 --- a/tl/src/TlWriter.kt +++ b/tl/src/TlWriter.kt @@ -1,63 +1,75 @@ package org.ton.tl -import io.ktor.utils.io.core.* +import kotlinx.io.* +import kotlinx.io.bytestring.ByteString import org.ton.tl.constructors.Bool import org.ton.tl.constructors.BoolTlCombinator public class TlWriter( - public val output: Output = BytePacketBuilder() + public val output: Sink ) { public fun writeBoolean(value: Boolean) { BoolTlCombinator.encode(this, Bool[value]) } public fun writeInt(value: Int) { - output.writeIntLittleEndian(value) + output.writeIntLe(value) } public fun writeLong(value: Long) { - output.writeLongLittleEndian(value) + output.writeLongLe(value) } public fun writeRaw(value: ByteArray) { - output.writeFully(value) + output.write(value) } public fun writeRaw(value: ByteString) { - output.writeFully(value.data) + output.write(value) } - public fun writeBytes(value: ByteString, offset: Int = 0, length: Int = value.size) { - writeBytes(value.data, offset, length) + public fun writeBytes(value: ByteString, startIndex: Int = 0, endIndex: Int = value.size) { + val length = endIndex - startIndex + val lengthSize = writeLength(length) + var totalLength = length + lengthSize + output.write(value, startIndex, endIndex) + while (totalLength++ % 4 > 0) { + output.writeByte(0) + } } - public fun writeBytes(value: ByteArray, offset: Int = 0, length: Int = value.size - offset) { - var totalLength = length - if (totalLength < 254) { - output.writeUByte(totalLength.toUByte()) - totalLength++ - } else if (totalLength < (1 shl 24)) { + public fun writeBytes(value: ByteArray, startIndex: Int = 0, endIndex: Int = value.size) { + val length = endIndex - startIndex + val lengthSize = writeLength(length) + var totalLength = length + lengthSize + output.write(value, startIndex, endIndex) + while (totalLength++ % 4 > 0) { + output.writeByte(0) + } + } + + private fun writeLength(length: Int): Int { + if (length < 254) { + output.writeUByte(length.toUByte()) + return 1 + } else if (length < (1 shl 24)) { output.writeUByte(254u) - output.writeUByte((totalLength and 255).toUByte()) - output.writeUByte(((totalLength shr 8) and 255).toUByte()) - output.writeUByte((totalLength shr 16).toUByte()) - totalLength += 4 - } else if (totalLength < Int.MAX_VALUE) { + output.writeUByte((length and 255).toUByte()) + output.writeUByte(((length shr 8) and 255).toUByte()) + output.writeUByte((length shr 16).toUByte()) + return 4 + } else if (length < Int.MAX_VALUE) { output.writeUByte(255u) - output.writeUByte((totalLength and 255).toUByte()) - output.writeUByte(((totalLength shr 8) and 255).toUByte()) - output.writeUByte(((totalLength shr 16) and 255).toUByte()) - output.writeUByte(((totalLength shr 24) and 255).toUByte()) + output.writeUByte((length and 255).toUByte()) + output.writeUByte(((length shr 8) and 255).toUByte()) + output.writeUByte(((length shr 16) and 255).toUByte()) + output.writeUByte(((length shr 24) and 255).toUByte()) output.writeByte(0) output.writeByte(0) output.writeByte(0) - totalLength += 8 + return 8 } else { - throw IllegalStateException("Too big byte array: $totalLength") - } - output.writeFully(value, offset, length) - while (totalLength++ % 4 > 0) { - output.writeByte(0) + throw IllegalStateException("Too big byte array: $length") } } diff --git a/tl/src/constructors/BytesTlConstructor.kt b/tl/src/constructors/BytesTlConstructor.kt index bf234980..42843542 100644 --- a/tl/src/constructors/BytesTlConstructor.kt +++ b/tl/src/constructors/BytesTlConstructor.kt @@ -2,7 +2,7 @@ package org.ton.tl.constructors -import org.ton.tl.ByteString +import kotlinx.io.bytestring.ByteString import org.ton.tl.TlConstructor import org.ton.tl.TlReader import org.ton.tl.TlWriter diff --git a/tonapi-tl/src/SignedTlObject.kt b/tonapi-tl/src/SignedTlObject.kt index 8d8e8f70..4ff56625 100644 --- a/tonapi-tl/src/SignedTlObject.kt +++ b/tonapi-tl/src/SignedTlObject.kt @@ -1,8 +1,8 @@ package org.ton.api +import kotlinx.io.bytestring.ByteString import org.ton.api.pk.PrivateKey import org.ton.api.pub.PublicKey -import org.ton.tl.ByteString import org.ton.tl.TlObject public interface SignedTlObject> : TlObject { diff --git a/tonapi-tl/src/adnl/AdnlAddress.kt b/tonapi-tl/src/adnl/AdnlAddress.kt index 702716d6..b18a3a8a 100644 --- a/tonapi-tl/src/adnl/AdnlAddress.kt +++ b/tonapi-tl/src/adnl/AdnlAddress.kt @@ -2,6 +2,7 @@ package org.ton.api.adnl +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.Polymorphic import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -10,7 +11,6 @@ import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonClassDiscriminator import org.ton.api.pub.PublicKey import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString import kotlin.jvm.JvmName @Polymorphic @@ -65,11 +65,10 @@ public data class AdnlAddressUdp( @SerialName("adnl.address.udp6") @Serializable public data class AdnlAddressUdp6( + @Serializable(ByteStringBase64Serializer::class) override val ip: ByteString, override val port: Int ) : AdnlAddress, AdnlIp6 { - public constructor(ip: ByteArray, port: Int) : this(ip.toByteString(), port) - public companion object : TlConstructor( schema = "adnl.address.udp6 ip:int128 port:int = adnl.Address" ) { @@ -91,14 +90,12 @@ public data class AdnlAddressUdp6( @Serializable public data class AdnlAddressTunnel( @get:JvmName("to") + @Serializable(ByteStringBase64Serializer::class) val to: ByteString, @get:JvmName("pubKey") val pubKey: PublicKey ) : AdnlAddress { - public constructor(to: ByteArray, pubKey: PublicKey) : this(to.toByteString(), pubKey) - public constructor(adnlIdShort: AdnlIdShort, pubKey: PublicKey) : this(adnlIdShort.id, pubKey) - public companion object : TlConstructor( schema = "adnl.address.tunnel to:int256 pubkey:PublicKey = adnl.Address" ) { diff --git a/tonapi-tl/src/adnl/AdnlAddressList.kt b/tonapi-tl/src/adnl/AdnlAddressList.kt index 67fe9f7a..60845688 100644 --- a/tonapi-tl/src/adnl/AdnlAddressList.kt +++ b/tonapi-tl/src/adnl/AdnlAddressList.kt @@ -24,8 +24,6 @@ public data class AdnlAddressList( @get:JvmName("expireAt") val expireAt: Int = 0 ) : TlObject { - public constructor(vararg addrs: AdnlAddress) : this(addrs.toList()) - override fun tlCodec(): TlCodec = Companion public companion object : TlConstructor( diff --git a/tonapi-tl/src/adnl/AdnlIdShort.kt b/tonapi-tl/src/adnl/AdnlIdShort.kt index cbbb7769..abc5f8cc 100644 --- a/tonapi-tl/src/adnl/AdnlIdShort.kt +++ b/tonapi-tl/src/adnl/AdnlIdShort.kt @@ -2,6 +2,7 @@ package org.ton.api.adnl +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.overlay.OverlayNode @@ -12,6 +13,7 @@ import kotlin.jvm.JvmStatic @Serializable @SerialName("adnl.id.short") public data class AdnlIdShort( + @Serializable(ByteStringBase64Serializer::class) val id: ByteString ) : Comparable, TlObject { public fun verify(node: OverlayNode): Boolean { diff --git a/tonapi-tl/src/adnl/AdnlNode.kt b/tonapi-tl/src/adnl/AdnlNode.kt index 19856511..fc08bb7b 100644 --- a/tonapi-tl/src/adnl/AdnlNode.kt +++ b/tonapi-tl/src/adnl/AdnlNode.kt @@ -16,11 +16,6 @@ public data class AdnlNode( @get:JvmName("addrList") val addrList: AdnlAddressList ) { - public constructor( - id: PublicKey, - addrList: List - ) : this(id, AdnlAddressList(addrList)) - public companion object : TlConstructor( schema = "adnl.node id:PublicKey addr_list:adnl.addressList = adnl.Node" ) { diff --git a/tonapi-tl/src/adnl/AdnlPacketContents.kt b/tonapi-tl/src/adnl/AdnlPacketContents.kt index be3fac92..280a1034 100644 --- a/tonapi-tl/src/adnl/AdnlPacketContents.kt +++ b/tonapi-tl/src/adnl/AdnlPacketContents.kt @@ -1,5 +1,6 @@ package org.ton.api.adnl +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.SignedTlObject @@ -22,6 +23,7 @@ import kotlin.random.Random @SerialName("adnl.packetContents") public data class AdnlPacketContents( @get:JvmName("rand1") + @Serializable(ByteStringBase64Serializer::class) val rand1: ByteString, @get:JvmName("flags") @@ -71,13 +73,15 @@ public data class AdnlPacketContents( val dstReinitDate: Int?, @get:JvmName("signature") + @Serializable(ByteStringBase64Serializer::class) override val signature: ByteString?, @get:JvmName("rand2") + @Serializable(ByteStringBase64Serializer::class) val rand2: ByteString ) : SignedTlObject { public constructor( - rand1: ByteString = Random.Default.nextBytes(if (Random.nextBoolean()) 7 else 15).asByteString(), + rand1: ByteString = ByteString(*Random.Default.nextBytes(if (Random.nextBoolean()) 7 else 15)), from: PublicKey? = null, from_short: AdnlIdShort? = null, message: AdnlMessage? = null, @@ -91,7 +95,7 @@ public data class AdnlPacketContents( reinit_date: Int? = null, dst_reinit_date: Int? = null, signature: ByteString? = null, - rand2: ByteString = Random.Default.nextBytes(if (Random.nextBoolean()) 7 else 15).asByteString() + rand2: ByteString = ByteString(*Random.Default.nextBytes(if (Random.nextBoolean()) 7 else 15)) ) : this( rand1 = rand1, flags = flags( @@ -176,7 +180,7 @@ public data class AdnlPacketContents( recv_priority_addr_list_version = recvPriorityAddrListVersion, reinit_date = reinitDate, dst_reinit_date = dstReinitDate, - signature = signature.asByteString(), + signature = ByteString(*signature), rand2 = rand2 ) } diff --git a/tonapi-tl/src/adnl/AdnlProxy.kt b/tonapi-tl/src/adnl/AdnlProxy.kt index 29fd82f0..e12bd494 100644 --- a/tonapi-tl/src/adnl/AdnlProxy.kt +++ b/tonapi-tl/src/adnl/AdnlProxy.kt @@ -2,6 +2,7 @@ package org.ton.api.adnl +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonClassDiscriminator @@ -23,6 +24,7 @@ public interface AdnlProxy { @Serializable public data class AdnlProxyNone( @get:JvmName("id") + @Serializable(ByteStringBase64Serializer::class) override val id: ByteString ) : AdnlProxy { public companion object : TlConstructor( @@ -43,9 +45,11 @@ public data class AdnlProxyNone( @Serializable public data class AdnlProxyFast( @get:JvmName("id") + @Serializable(ByteStringBase64Serializer::class) override val id: ByteString, @get:JvmName("sharedSecret") + @Serializable(ByteStringBase64Serializer::class) val sharedSecret: ByteString ) : AdnlProxy { public companion object : TlConstructor( diff --git a/tonapi-tl/src/adnl/AdnlProxyTo.kt b/tonapi-tl/src/adnl/AdnlProxyTo.kt index 692294d4..703adc8f 100644 --- a/tonapi-tl/src/adnl/AdnlProxyTo.kt +++ b/tonapi-tl/src/adnl/AdnlProxyTo.kt @@ -1,9 +1,9 @@ package org.ton.api.adnl +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import org.ton.tl.ByteString -import org.ton.tl.ByteString.Companion.toByteString +import org.ton.tl.ByteStringBase64Serializer import org.ton.tl.TlConstructor import org.ton.tl.TlReader import org.ton.tl.TlWriter @@ -23,20 +23,14 @@ public data class AdnlProxyTo( @SerialName("date_hash") @get:JvmName("dateHash") + @Serializable(ByteStringBase64Serializer::class) val dateHash: ByteString, @SerialName("shared_secret") @get:JvmName("sharedSecret") + @Serializable(ByteStringBase64Serializer::class) val sharedSecret: ByteString ) { - public constructor( - ip: Int, - port: Int, - date: Int, - dateHash: ByteArray, - sharedSecret: ByteArray - ) : this(ip, port, date, dateHash.toByteString(), sharedSecret.toByteString()) - public companion object : TlConstructor( schema = "adnl.proxyToFastHash ip:int port:int date:int data_hash:int256 shared_secret:int256 = adnl.ProxyTo" ) { @@ -52,8 +46,8 @@ public data class AdnlProxyTo( val ip = reader.readInt() val port = reader.readInt() val date = reader.readInt() - val dateHash = reader.readRaw(32) - val sharedSecret = reader.readRaw(32) + val dateHash = reader.readByteString(32) + val sharedSecret = reader.readByteString(32) return AdnlProxyTo(ip, port, date, dateHash, sharedSecret) } } diff --git a/tonapi-tl/src/adnl/AdnlProxyToSign.kt b/tonapi-tl/src/adnl/AdnlProxyToSign.kt index 4eeced7f..be87d952 100644 --- a/tonapi-tl/src/adnl/AdnlProxyToSign.kt +++ b/tonapi-tl/src/adnl/AdnlProxyToSign.kt @@ -1,9 +1,9 @@ package org.ton.api.adnl +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import org.ton.tl.ByteString -import org.ton.tl.ByteString.Companion.toByteString +import org.ton.tl.ByteStringBase64Serializer import org.ton.tl.TlConstructor import org.ton.tl.TlReader import org.ton.tl.TlWriter @@ -22,6 +22,7 @@ public data class AdnlProxyToSign( val date: Int, @get:JvmName("signature") + @Serializable(ByteStringBase64Serializer::class) val signature: ByteString ) { public constructor( @@ -29,7 +30,7 @@ public data class AdnlProxyToSign( port: Int, date: Int, signature: ByteArray - ) : this(ip, port, date, signature.toByteString()) + ) : this(ip, port, date, ByteString(signature)) init { require(signature.size == 32) diff --git a/tonapi-tl/src/adnl/message/AdnlMessageAnswer.kt b/tonapi-tl/src/adnl/message/AdnlMessageAnswer.kt index bff28a99..0afab25d 100644 --- a/tonapi-tl/src/adnl/message/AdnlMessageAnswer.kt +++ b/tonapi-tl/src/adnl/message/AdnlMessageAnswer.kt @@ -1,9 +1,9 @@ package org.ton.api.adnl.message +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString import org.ton.tl.constructors.BytesTlConstructor import kotlin.jvm.JvmName @@ -12,13 +12,13 @@ import kotlin.jvm.JvmName public data class AdnlMessageAnswer( @SerialName("query_id") @get:JvmName("queryId") + @Serializable(ByteStringBase64Serializer::class) val queryId: ByteString, @get:JvmName("answer") + @Serializable(ByteStringBase64Serializer::class) val answer: ByteString ) : AdnlMessage { - public constructor(queryId: ByteArray, answer: ByteArray) : this(queryId.toByteString(), answer.toByteString()) - init { require(queryId.size == 32) } @@ -35,8 +35,8 @@ public data class AdnlMessageAnswer( } override fun decode(reader: TlReader): AdnlMessageAnswer = reader { - val queryId = readRaw(32) - val answer = readBytes() + val queryId = readByteString(32) + val answer = readByteString() AdnlMessageAnswer(queryId, answer) } } diff --git a/tonapi-tl/src/adnl/message/AdnlMessageConfirmChannel.kt b/tonapi-tl/src/adnl/message/AdnlMessageConfirmChannel.kt index 1fe8816a..0f977392 100644 --- a/tonapi-tl/src/adnl/message/AdnlMessageConfirmChannel.kt +++ b/tonapi-tl/src/adnl/message/AdnlMessageConfirmChannel.kt @@ -2,11 +2,10 @@ package org.ton.api.adnl.message -import kotlinx.datetime.Instant +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import org.ton.tl.ByteString -import org.ton.tl.ByteString.Companion.toByteString +import org.ton.tl.ByteStringBase64Serializer import org.ton.tl.TlConstructor import org.ton.tl.TlReader import org.ton.tl.TlWriter @@ -16,29 +15,17 @@ import kotlin.jvm.JvmName @Serializable public data class AdnlMessageConfirmChannel( @get:JvmName("key") + @Serializable(ByteStringBase64Serializer::class) val key: ByteString, @SerialName("peer_key") @get:JvmName("peerKey") + @Serializable(ByteStringBase64Serializer::class) val peerKey: ByteString, @get:JvmName("date") val date: Int ) : AdnlMessage { - public constructor( - key: ByteArray, - peerKey: ByteArray, - date: Int - ) : this(key.toByteString(), peerKey.toByteString(), date) - - public constructor( - key: ByteString, - peerKey: ByteString, - date: Instant - ) : this(key, peerKey, date.epochSeconds.toInt()) - - public fun date(): Instant = Instant.fromEpochSeconds(date.toUInt().toLong()) - public companion object : TlConstructor( schema = "adnl.message.confirmChannel key:int256 peer_key:int256 date:int = adnl.Message", ) { diff --git a/tonapi-tl/src/adnl/message/AdnlMessageCreateChannel.kt b/tonapi-tl/src/adnl/message/AdnlMessageCreateChannel.kt index 0c0326e7..9d8eadf1 100644 --- a/tonapi-tl/src/adnl/message/AdnlMessageCreateChannel.kt +++ b/tonapi-tl/src/adnl/message/AdnlMessageCreateChannel.kt @@ -1,10 +1,9 @@ package org.ton.api.adnl.message -import kotlinx.datetime.Instant +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import org.ton.tl.ByteString -import org.ton.tl.ByteString.Companion.toByteString +import org.ton.tl.ByteStringBase64Serializer import org.ton.tl.TlConstructor import org.ton.tl.TlReader import org.ton.tl.TlWriter @@ -14,18 +13,12 @@ import kotlin.jvm.JvmName @Serializable public data class AdnlMessageCreateChannel( @get:JvmName("key") + @Serializable(ByteStringBase64Serializer::class) val key: ByteString, @get:JvmName("date") val date: Int ) : AdnlMessage { - public constructor( - key: ByteArray, - date: Instant - ) : this(key.toByteString(), date.epochSeconds.toUInt().toInt()) - - public fun date(): Instant = Instant.fromEpochSeconds(date.toUInt().toLong()) - public companion object : TlConstructor( schema = "adnl.message.createChannel key:int256 date:int = adnl.Message", ) { diff --git a/tonapi-tl/src/adnl/message/AdnlMessageCustom.kt b/tonapi-tl/src/adnl/message/AdnlMessageCustom.kt index 046e25c5..58a3aacb 100644 --- a/tonapi-tl/src/adnl/message/AdnlMessageCustom.kt +++ b/tonapi-tl/src/adnl/message/AdnlMessageCustom.kt @@ -1,8 +1,9 @@ package org.ton.api.adnl.message +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import org.ton.tl.ByteString +import org.ton.tl.ByteStringBase64Serializer import org.ton.tl.TlConstructor import org.ton.tl.TlReader import org.ton.tl.TlWriter @@ -13,6 +14,7 @@ import kotlin.jvm.JvmName @Serializable public data class AdnlMessageCustom( @get:JvmName("data") + @Serializable(ByteStringBase64Serializer::class) val data: ByteString ) : AdnlMessage { public companion object : TlConstructor( diff --git a/tonapi-tl/src/adnl/message/AdnlMessagePart.kt b/tonapi-tl/src/adnl/message/AdnlMessagePart.kt index e7a02ea1..081b856b 100644 --- a/tonapi-tl/src/adnl/message/AdnlMessagePart.kt +++ b/tonapi-tl/src/adnl/message/AdnlMessagePart.kt @@ -1,9 +1,9 @@ package org.ton.api.adnl.message +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString import org.ton.tl.constructors.BytesTlConstructor import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -12,6 +12,7 @@ import kotlin.jvm.JvmStatic @Serializable public data class AdnlMessagePart( @get:JvmName("hash") + @Serializable(ByteStringBase64Serializer::class) val hash: ByteString, @SerialName("total_size") @@ -22,15 +23,9 @@ public data class AdnlMessagePart( val offset: Int, @get:JvmName("data") + @Serializable(ByteStringBase64Serializer::class) val data: ByteString ) : AdnlMessage { - public constructor( - hash: ByteArray, - totalSize: Int, - offset: Int, - data: ByteArray, - ) : this(hash.toByteString(), totalSize, offset, data.toByteString()) - init { check(hash.size == 32) { "hash size expected: 32, actual: ${hash.size}" } } @@ -55,10 +50,10 @@ public data class AdnlMessagePart( while (offset < data.size) { val partSize = minOf(maxSize, data.size - offset) val part = AdnlMessagePart( - hash = hash, + hash = ByteString(*hash), totalSize = data.size, offset = offset, - data = data.copyOfRange(offset, offset + partSize) + data = ByteString(*data.copyOfRange(offset, offset + partSize)) ) parts.add(part) offset += partSize diff --git a/tonapi-tl/src/adnl/message/AdnlMessageQuery.kt b/tonapi-tl/src/adnl/message/AdnlMessageQuery.kt index df37ed35..1adbaabc 100644 --- a/tonapi-tl/src/adnl/message/AdnlMessageQuery.kt +++ b/tonapi-tl/src/adnl/message/AdnlMessageQuery.kt @@ -1,8 +1,9 @@ package org.ton.api.adnl.message +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import org.ton.tl.ByteString +import org.ton.tl.ByteStringBase64Serializer import org.ton.tl.TlConstructor import org.ton.tl.TlReader import org.ton.tl.TlWriter @@ -14,9 +15,11 @@ import kotlin.jvm.JvmName public data class AdnlMessageQuery( @SerialName("query_id") @get:JvmName("queryId") + @Serializable(ByteStringBase64Serializer::class) val queryId: ByteString, @get:JvmName("query") + @Serializable(ByteStringBase64Serializer::class) val query: ByteString ) : AdnlMessage { public companion object : TlConstructor( diff --git a/tonapi-tl/src/control/ControlConfigLocal.kt b/tonapi-tl/src/control/ControlConfigLocal.kt index ac72439d..a0d39fdf 100644 --- a/tonapi-tl/src/control/ControlConfigLocal.kt +++ b/tonapi-tl/src/control/ControlConfigLocal.kt @@ -1,11 +1,12 @@ package org.ton.api.control +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.Polymorphic import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonClassDiscriminator import org.ton.api.pk.PrivateKey -import org.ton.tl.ByteString +import org.ton.tl.ByteStringBase64Serializer @Serializable @Polymorphic @@ -13,6 +14,7 @@ import org.ton.tl.ByteString @JsonClassDiscriminator("@type") public data class ControlConfigLocal( val priv: PrivateKey, + @Serializable(ByteStringBase64Serializer::class) val pub: ByteString, val port: Int ) diff --git a/tonapi-tl/src/dht/DhtKey.kt b/tonapi-tl/src/dht/DhtKey.kt index 85c1c838..3e2618de 100644 --- a/tonapi-tl/src/dht/DhtKey.kt +++ b/tonapi-tl/src/dht/DhtKey.kt @@ -1,9 +1,9 @@ package org.ton.api.dht +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.Serializable import org.ton.api.adnl.AdnlIdShort import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString import kotlin.jvm.JvmName import kotlin.jvm.JvmOverloads import kotlin.jvm.JvmStatic @@ -12,6 +12,7 @@ import kotlin.jvm.JvmStatic public data class DhtKey @JvmOverloads constructor( @get:JvmName("id") + @Serializable(ByteStringBase64Serializer::class) val id: ByteString, @get:JvmName("name") @@ -20,35 +21,25 @@ public data class DhtKey @get:JvmName("idx") val idx: Int = 0 ) : TlObject { - @JvmOverloads - public constructor(id: ByteArray, name: String, idx: Int = 0) : this(id.toByteString(), name, idx) - - @JvmOverloads - public constructor(id: AdnlIdShort, name: String, idx: Int = 0) : this(id.id, name, idx) - - init { - require(id.size == 256) - } - override fun tlCodec(): TlCodec = DhtKey public companion object : TlConstructor( schema = "dht.key id:int256 name:bytes idx:int = dht.Key" ) { @JvmStatic - public fun address(adnlIdShort: AdnlIdShort): DhtKey = DhtKey(adnlIdShort, "address") + public fun address(adnlIdShort: AdnlIdShort): DhtKey = DhtKey(adnlIdShort.id, "address") @JvmStatic - public fun nodes(adnlIdShort: AdnlIdShort): DhtKey = DhtKey(adnlIdShort, "nodes") + public fun nodes(adnlIdShort: AdnlIdShort): DhtKey = DhtKey(adnlIdShort.id, "nodes") override fun encode(writer: TlWriter, value: DhtKey) { - writer.writeRaw(value.id.toByteArray()) + writer.writeRaw(value.id) writer.writeString(value.name) writer.writeInt(value.idx) } override fun decode(reader: TlReader): DhtKey { - val id = reader.readRaw(32) + val id = reader.readByteString(32) val name = reader.readString() val idx = reader.readInt() return DhtKey(id, name, idx) diff --git a/tonapi-tl/src/dht/DhtKeyDescription.kt b/tonapi-tl/src/dht/DhtKeyDescription.kt index 63dcb1b5..b79d9dfa 100644 --- a/tonapi-tl/src/dht/DhtKeyDescription.kt +++ b/tonapi-tl/src/dht/DhtKeyDescription.kt @@ -1,5 +1,6 @@ package org.ton.api.dht +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.SignedTlObject @@ -14,17 +15,20 @@ public data class DhtKeyDescription( val id: PublicKey, @SerialName("update_rule") val updateRule: DhtUpdateRule = DhtUpdateRule.SIGNATURE, - override val signature: ByteString = ByteString.of() + @Serializable(ByteStringBase64Serializer::class) + override val signature: ByteString = ByteString() ) : SignedTlObject { override fun signed(privateKey: PrivateKey): DhtKeyDescription = copy( - signature = privateKey.sign( - copy(signature = ByteArray(0).asByteString()).toByteArray() - ).asByteString() + signature = ByteString( + * privateKey.sign( + copy(signature = ByteString()).toByteArray() + ) + ) ) override fun verify(publicKey: PublicKey): Boolean = - publicKey.verify(tlCodec().encodeToByteArray(copy(signature = ByteArray(0).asByteString())), signature.toByteArray()) + publicKey.verify(tlCodec().encodeToByteArray(copy(signature = ByteString())), signature.toByteArray()) override fun tlCodec(): TlCodec = DhtKeyDescriptionTlConstructor @@ -33,7 +37,7 @@ public data class DhtKeyDescription( public fun signed(name: String, key: PrivateKey): DhtKeyDescription { val keyDescription = DhtKeyDescription( id = key.publicKey(), - key = DhtKey(key.publicKey().toAdnlIdShort(), name) + key = DhtKey(key.publicKey().toAdnlIdShort().id, name) ) return keyDescription.signed(key) } diff --git a/tonapi-tl/src/dht/DhtNode.kt b/tonapi-tl/src/dht/DhtNode.kt index eba590ea..afec518a 100644 --- a/tonapi-tl/src/dht/DhtNode.kt +++ b/tonapi-tl/src/dht/DhtNode.kt @@ -1,5 +1,6 @@ package org.ton.api.dht +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.SignedTlObject @@ -24,16 +25,17 @@ public data class DhtNode( val version: Int = 0, @get:JvmName("signature") + @Serializable(ByteStringBase64Serializer::class) override val signature: ByteString ) : SignedTlObject { public fun toAdnlNode(): AdnlNode = AdnlNode(id, addrList) public fun key(): AdnlIdShort = id.toAdnlIdShort() override fun signed(privateKey: PrivateKey): DhtNode = - copy(signature = ByteString.of(*privateKey.sign(tlCodec().encodeToByteArray(this)))) + copy(signature = ByteString(*privateKey.sign(tlCodec().encodeToByteArray(this)))) override fun verify(publicKey: PublicKey): Boolean = - publicKey.verify(tlCodec().encodeToByteArray(copy(signature = ByteString.of())), signature.toByteArray()) + publicKey.verify(tlCodec().encodeToByteArray(copy(signature = ByteString())), signature.toByteArray()) override fun tlCodec(): TlCodec = DhtNodeTlConstructor diff --git a/tonapi-tl/src/dht/DhtValue.kt b/tonapi-tl/src/dht/DhtValue.kt index 694762c2..1be5a6e8 100644 --- a/tonapi-tl/src/dht/DhtValue.kt +++ b/tonapi-tl/src/dht/DhtValue.kt @@ -1,5 +1,6 @@ package org.ton.api.dht +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.Serializable import org.ton.api.SignedTlObject import org.ton.api.pk.PrivateKey @@ -11,16 +12,21 @@ import kotlin.jvm.JvmName public data class DhtValue( @get:JvmName("key") val key: DhtKeyDescription, + @Serializable(ByteStringBase64Serializer::class) val value: ByteString, val ttl: Int, - override val signature: ByteString = ByteString.of() + @Serializable(ByteStringBase64Serializer::class) + override val signature: ByteString = ByteString() ) : SignedTlObject { override fun signed(privateKey: PrivateKey): DhtValue = - copy(signature = privateKey.sign(tlCodec().encodeToByteArray(this)).asByteString()) + copy(signature = ByteString(* privateKey.sign(tlCodec().encodeToByteArray(this)))) override fun verify(publicKey: PublicKey): Boolean = - publicKey.verify(tlCodec().encodeToByteArray(copy(signature = ByteArray(0).asByteString())), signature.toByteArray()) + publicKey.verify( + tlCodec().encodeToByteArray(copy(signature = ByteString())), + signature.toByteArray() + ) override fun tlCodec(): TlCodec = DhtValue diff --git a/tonapi-tl/src/dht/functions/DhtFindValue.kt b/tonapi-tl/src/dht/functions/DhtFindValue.kt index 1ec8b10a..9b9420c4 100644 --- a/tonapi-tl/src/dht/functions/DhtFindValue.kt +++ b/tonapi-tl/src/dht/functions/DhtFindValue.kt @@ -1,15 +1,15 @@ package org.ton.api.dht.functions +import kotlinx.io.bytestring.ByteString import org.ton.api.dht.DhtKey import org.ton.api.dht.DhtValueResult import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString public data class DhtFindValue( val key: ByteString, val k: Int ) : TLFunction { - public constructor(key: ByteArray, k: Int) : this((key).toByteString(), k) + public constructor(key: ByteArray, k: Int) : this(ByteString(key), k) public constructor(key: DhtKey, k: Int) : this(key.hash(), k) override fun tlCodec(): TlCodec = DhtFindValueTlConstructor diff --git a/tonapi-tl/src/http/HttpPayloadPart.kt b/tonapi-tl/src/http/HttpPayloadPart.kt index 8523c925..f0a5a533 100644 --- a/tonapi-tl/src/http/HttpPayloadPart.kt +++ b/tonapi-tl/src/http/HttpPayloadPart.kt @@ -1,6 +1,6 @@ package org.ton.api.http -import io.ktor.util.* +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.tl.* @@ -8,33 +8,13 @@ import org.ton.tl.* @SerialName("http.payloadPart") @Serializable public data class HttpPayloadPart( - val data: ByteArray, + @Serializable(ByteStringBase64Serializer::class) + val data: ByteString, val trailer: Collection, val last: Boolean ) : TlObject { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is HttpPayloadPart) return false - - if (!data.contentEquals(other.data)) return false - if (trailer != other.trailer) return false - if (last != other.last) return false - - return true - } - - override fun hashCode(): Int { - var result = data.contentHashCode() - result = 31 * result + trailer.hashCode() - result = 31 * result + last.hashCode() - return result - } - override fun tlCodec(): TlCodec = Companion - override fun toString(): String = - "HttpPayloadPart(trailer=$trailer, last=$last, data=(${data.size} bytes) ${data.encodeBase64()})" - public companion object : TlCodec by HttpPayloadPartTlConstructor } @@ -42,7 +22,7 @@ private object HttpPayloadPartTlConstructor : TlConstructor( schema = "http.payloadPart data:bytes trailer:(vector http.header) last:Bool = http.PayloadPart" ) { override fun decode(reader: TlReader): HttpPayloadPart { - val data = reader.readBytes() + val data = reader.readByteString() val trailer = reader.readVector { read(HttpHeader) } diff --git a/tonapi-tl/src/http/functions/HttpGetNextPayloadPart.kt b/tonapi-tl/src/http/functions/HttpGetNextPayloadPart.kt index c821f37f..03dfa7de 100644 --- a/tonapi-tl/src/http/functions/HttpGetNextPayloadPart.kt +++ b/tonapi-tl/src/http/functions/HttpGetNextPayloadPart.kt @@ -1,5 +1,6 @@ package org.ton.api.http.functions +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.http.HttpPayloadPart @@ -8,29 +9,12 @@ import org.ton.tl.* @SerialName("http.getNextPayloadPart") @Serializable public data class HttpGetNextPayloadPart( + @Serializable(ByteStringBase64Serializer::class) val id: ByteString, val seqno: Int, @SerialName("max_chunk_size") val maxChunkSize: Int ) : TLFunction { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is HttpGetNextPayloadPart) return false - - if (id != other.id) return false - if (seqno != other.seqno) return false - if (maxChunkSize != other.maxChunkSize) return false - - return true - } - - override fun hashCode(): Int { - var result = id.hashCode() - result = 31 * result + seqno - result = 31 * result + maxChunkSize - return result - } - override fun tlCodec(): TlCodec = Companion override fun resultTlCodec(): TlCodec = HttpPayloadPart diff --git a/tonapi-tl/src/http/functions/HttpRequest.kt b/tonapi-tl/src/http/functions/HttpRequest.kt index a8b89e8e..1cd4714c 100644 --- a/tonapi-tl/src/http/functions/HttpRequest.kt +++ b/tonapi-tl/src/http/functions/HttpRequest.kt @@ -1,5 +1,6 @@ package org.ton.api.http.functions +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.http.HttpHeader @@ -9,6 +10,7 @@ import org.ton.tl.* @SerialName("http.request") @Serializable public data class HttpRequest( + @Serializable(ByteStringBase64Serializer::class) val id: ByteString, val method: String, val url: String, diff --git a/tonapi-tl/src/overlay/OverlayNode.kt b/tonapi-tl/src/overlay/OverlayNode.kt index b41e6bb8..35909722 100644 --- a/tonapi-tl/src/overlay/OverlayNode.kt +++ b/tonapi-tl/src/overlay/OverlayNode.kt @@ -1,37 +1,31 @@ package org.ton.api.overlay +import kotlinx.io.bytestring.ByteString +import kotlinx.io.bytestring.isEmpty import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.SignedTlObject import org.ton.api.pk.PrivateKey import org.ton.api.pub.PublicKey import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString @Serializable @SerialName("overlay.node") public data class OverlayNode( val id: PublicKey, + @Serializable(ByteStringBase64Serializer::class) val overlay: ByteString, val version: Int, - override val signature: ByteString = ByteString.of() + @Serializable(ByteStringBase64Serializer::class) + override val signature: ByteString = ByteString() ) : SignedTlObject { - public constructor( - id: PublicKey, - overlay: ByteArray, - version: Int, - signature: ByteArray = ByteArray(0) - ) : this( - id, overlay.toByteString(), version, signature.toByteString() - ) override fun signed(privateKey: PrivateKey): OverlayNode = copy( - signature = ByteString.of( + signature = ByteString( *privateKey.sign( tlCodec().encodeToByteArray( - if (signature.isEmpty()) this - else copy(signature = ByteString.of()) + copy(signature = ByteString()) ) ) ) @@ -40,7 +34,7 @@ public data class OverlayNode( override fun verify(publicKey: PublicKey): Boolean { if (signature.isEmpty()) return false val check = copy( - signature = ByteString.of() + signature = ByteString() ) return publicKey.verify(tlCodec().encodeToByteArray(check), signature.toByteArray()) } diff --git a/tonapi-tl/src/overlay/OverlayNodeToSign.kt b/tonapi-tl/src/overlay/OverlayNodeToSign.kt index 59148170..690ecc28 100644 --- a/tonapi-tl/src/overlay/OverlayNodeToSign.kt +++ b/tonapi-tl/src/overlay/OverlayNodeToSign.kt @@ -1,5 +1,6 @@ package org.ton.api.overlay +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.adnl.AdnlIdShort @@ -9,6 +10,7 @@ import org.ton.tl.* @SerialName("overlay.node.toSign") public data class OverlayNodeToSign( val id: AdnlIdShort, + @Serializable(ByteStringBase64Serializer::class) val overlay: ByteString, val version: Int ) : TlObject { diff --git a/tonapi-tl/src/pk/aes.kt b/tonapi-tl/src/pk/aes.kt index 0412f5f6..d6b5509c 100644 --- a/tonapi-tl/src/pk/aes.kt +++ b/tonapi-tl/src/pk/aes.kt @@ -1,12 +1,13 @@ package org.ton.api.pk +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonClassDiscriminator import org.ton.api.pub.PublicKeyAes import org.ton.crypto.Decryptor import org.ton.crypto.DecryptorAes -import org.ton.tl.ByteString +import org.ton.tl.ByteStringBase64Serializer import org.ton.tl.TlConstructor import org.ton.tl.TlReader import org.ton.tl.TlWriter @@ -15,6 +16,7 @@ import org.ton.tl.TlWriter @SerialName("pk.aes") @Serializable public data class PrivateKeyAes( + @Serializable(ByteStringBase64Serializer::class) val key: ByteString ) : PrivateKey, Decryptor by DecryptorAes(key.toByteArray()) { override fun publicKey(): PublicKeyAes = PublicKeyAes(key) diff --git a/tonapi-tl/src/pk/ed25519.kt b/tonapi-tl/src/pk/ed25519.kt index ad442574..d4a08e8f 100644 --- a/tonapi-tl/src/pk/ed25519.kt +++ b/tonapi-tl/src/pk/ed25519.kt @@ -1,5 +1,6 @@ package org.ton.api.pk +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.pub.PublicKeyEd25519 @@ -7,8 +8,10 @@ import org.ton.crypto.Decryptor import org.ton.crypto.DecryptorEd25519 import org.ton.crypto.Ed25519 import org.ton.crypto.SecureRandom -import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString +import org.ton.tl.ByteStringBase64Serializer +import org.ton.tl.TlConstructor +import org.ton.tl.TlReader +import org.ton.tl.TlWriter import kotlin.jvm.JvmStatic import kotlin.random.Random @@ -18,16 +21,17 @@ public inline fun PrivateKeyEd25519(random: Random = SecureRandom): PrivateKeyEd @Serializable @SerialName("pk.ed25519") public data class PrivateKeyEd25519( + @Serializable(ByteStringBase64Serializer::class) public val key: ByteString ) : PrivateKey, Decryptor { - public constructor(key: ByteArray) : this(key.toByteString()) + public constructor(key: ByteArray) : this(ByteString(key)) init { require(key.size == 32) { "key must be 32 byte long" } } private val _publicKey: PublicKeyEd25519 by lazy(LazyThreadSafetyMode.PUBLICATION) { - PublicKeyEd25519(Ed25519.publicKey(key.toByteArray()).asByteString()) + PublicKeyEd25519(ByteString(*Ed25519.publicKey(key.toByteArray()))) } private val _decryptor by lazy(LazyThreadSafetyMode.PUBLICATION) { DecryptorEd25519(key.toByteArray()) @@ -46,12 +50,12 @@ public data class PrivateKeyEd25519( @JvmStatic public fun generate(random: Random = SecureRandom): PrivateKeyEd25519 = - PrivateKeyEd25519(random.nextBytes(32).asByteString()) + PrivateKeyEd25519(ByteString(*random.nextBytes(32))) @JvmStatic public fun of(byteArray: ByteArray): PrivateKeyEd25519 = when (byteArray.size) { - Ed25519.KEY_SIZE_BYTES -> PrivateKeyEd25519(byteArray.toByteString()) + Ed25519.KEY_SIZE_BYTES -> PrivateKeyEd25519(byteArray) Ed25519.KEY_SIZE_BYTES + Int.SIZE_BYTES -> decodeBoxed(byteArray) else -> throw IllegalArgumentException("Invalid key size: ${byteArray.size}") } diff --git a/tonapi-tl/src/pk/overlay.kt b/tonapi-tl/src/pk/overlay.kt index 58f7c4f5..7822e93d 100644 --- a/tonapi-tl/src/pk/overlay.kt +++ b/tonapi-tl/src/pk/overlay.kt @@ -1,12 +1,13 @@ package org.ton.api.pk +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonClassDiscriminator import org.ton.api.pub.PublicKeyOverlay import org.ton.crypto.Decryptor import org.ton.crypto.DecryptorFail -import org.ton.tl.ByteString +import org.ton.tl.ByteStringBase64Serializer import org.ton.tl.TlConstructor import org.ton.tl.TlReader import org.ton.tl.TlWriter @@ -15,6 +16,7 @@ import org.ton.tl.TlWriter @SerialName("pk.overlay") @Serializable public data class PrivateKeyOverlay( + @Serializable(ByteStringBase64Serializer::class) val name: ByteString ) : PrivateKey, Decryptor by DecryptorFail { override fun publicKey(): PublicKeyOverlay = PublicKeyOverlay(name) diff --git a/tonapi-tl/src/pk/unenc.kt b/tonapi-tl/src/pk/unenc.kt index f90d4fdd..e5fc2ad0 100644 --- a/tonapi-tl/src/pk/unenc.kt +++ b/tonapi-tl/src/pk/unenc.kt @@ -1,13 +1,13 @@ package org.ton.api.pk +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonClassDiscriminator import org.ton.api.pub.PublicKeyUnencrypted import org.ton.crypto.Decryptor import org.ton.crypto.DecryptorNone -import org.ton.tl.ByteString -import org.ton.tl.ByteString.Companion.toByteString +import org.ton.tl.ByteStringBase64Serializer import org.ton.tl.TlConstructor import org.ton.tl.TlReader import org.ton.tl.TlWriter @@ -16,6 +16,7 @@ import org.ton.tl.TlWriter @SerialName("pk.unenc") @Serializable public data class PrivateKeyUnencrypted( + @Serializable(ByteStringBase64Serializer::class) val data: ByteString ) : PrivateKey, Decryptor by DecryptorNone { override fun publicKey(): PublicKeyUnencrypted = PublicKeyUnencrypted(data) @@ -30,8 +31,7 @@ public data class PrivateKeyUnencrypted( } override fun decode(reader: TlReader): PrivateKeyUnencrypted { - val data = reader.readBytes() - return PrivateKeyUnencrypted(data.toByteString()) + return PrivateKeyUnencrypted(reader.readByteString()) } } } diff --git a/tonapi-tl/src/pub/ed25519.kt b/tonapi-tl/src/pub/ed25519.kt index 82e7a556..400c0ca4 100644 --- a/tonapi-tl/src/pub/ed25519.kt +++ b/tonapi-tl/src/pub/ed25519.kt @@ -2,6 +2,7 @@ package org.ton.api.pub +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.Polymorphic import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -10,8 +11,10 @@ import org.ton.api.pk.PrivateKeyEd25519 import org.ton.crypto.Ed25519 import org.ton.crypto.Encryptor import org.ton.crypto.EncryptorEd25519 -import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString +import org.ton.tl.ByteStringBase64Serializer +import org.ton.tl.TlConstructor +import org.ton.tl.TlReader +import org.ton.tl.TlWriter import kotlin.jvm.JvmStatic public inline fun PublicKeyEd25519(privateKey: PrivateKeyEd25519): PublicKeyEd25519 = PublicKeyEd25519.of(privateKey) @@ -20,12 +23,13 @@ public inline fun PublicKeyEd25519(privateKey: PrivateKeyEd25519): PublicKeyEd25 @SerialName("pub.ed25519") @Polymorphic public data class PublicKeyEd25519( + @Serializable(ByteStringBase64Serializer::class) val key: ByteString ) : PublicKey, Encryptor { - public constructor(byteArray: ByteArray) : this(byteArray.toByteString()) + public constructor(byteArray: ByteArray) : this(ByteString(byteArray)) private val _adnlIdShort: AdnlIdShort by lazy(LazyThreadSafetyMode.PUBLICATION) { - AdnlIdShort(PublicKeyEd25519.hash(this).asByteString()) + AdnlIdShort(ByteString(*PublicKeyEd25519.hash(this))) } private val _encryptor by lazy(LazyThreadSafetyMode.PUBLICATION) { EncryptorEd25519(key.toByteArray()) @@ -38,7 +42,7 @@ public data class PublicKeyEd25519( ) { @JvmStatic public fun of(privateKey: PrivateKeyEd25519): PublicKeyEd25519 = - PublicKeyEd25519(Ed25519.publicKey(privateKey.key.toByteArray()).asByteString()) + PublicKeyEd25519(ByteString(*Ed25519.publicKey(privateKey.key.toByteArray()))) override fun encode(writer: TlWriter, value: PublicKeyEd25519) { writer.writeRaw(value.key) diff --git a/tonapi-tl/src/pub/pub.kt b/tonapi-tl/src/pub/pub.kt index ed861a44..ad5b00b5 100644 --- a/tonapi-tl/src/pub/pub.kt +++ b/tonapi-tl/src/pub/pub.kt @@ -2,6 +2,8 @@ package org.ton.api.pub +import kotlinx.io.bytestring.ByteString +import kotlinx.io.bytestring.isEmpty import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonClassDiscriminator @@ -33,10 +35,11 @@ public sealed interface PublicKey : Encryptor, TlObject { @SerialName("pub.unenc") @Serializable public data class PublicKeyUnencrypted( + @Serializable(ByteStringBase64Serializer::class) val data: ByteString ) : PublicKey, Encryptor by EncryptorNone { - override fun toAdnlIdShort(): AdnlIdShort = AdnlIdShort(PublicKeyUnencrypted.hash(this).asByteString()) + override fun toAdnlIdShort(): AdnlIdShort = AdnlIdShort(ByteString(*PublicKeyUnencrypted.hash(this))) public companion object : TlConstructor( schema = "pub.unenc data:bytes = PublicKey" @@ -55,10 +58,11 @@ public data class PublicKeyUnencrypted( @SerialName("pub.aes") @Serializable public data class PublicKeyAes( + @Serializable(ByteStringBase64Serializer::class) val key: ByteString ) : PublicKey, Encryptor by EncryptorAes(key.toByteArray()) { private val _adnlIdShort by lazy(LazyThreadSafetyMode.PUBLICATION) { - AdnlIdShort(hash(this).asByteString()) + AdnlIdShort(ByteString(* hash(this))) } override fun toAdnlIdShort(): AdnlIdShort = _adnlIdShort @@ -80,11 +84,12 @@ public data class PublicKeyAes( @SerialName("pub.overlay") @Serializable public data class PublicKeyOverlay( + @Serializable(ByteStringBase64Serializer::class) val name: ByteString ) : PublicKey, Encryptor by EncryptorFail { override fun toAdnlIdShort(): AdnlIdShort = AdnlIdShort( - PublicKeyOverlay.hash(this).asByteString() + ByteString(*PublicKeyOverlay.hash(this)) ) override fun verify(message: ByteArray, signature: ByteArray?): Boolean { diff --git a/tonapi-tl/src/rldp/RldpAnswer.kt b/tonapi-tl/src/rldp/RldpAnswer.kt index 30f493f1..42ab837e 100644 --- a/tonapi-tl/src/rldp/RldpAnswer.kt +++ b/tonapi-tl/src/rldp/RldpAnswer.kt @@ -1,5 +1,6 @@ package org.ton.api.rldp +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.tl.* @@ -8,7 +9,9 @@ import org.ton.tl.* @Serializable public data class RldpAnswer( @SerialName("query_id") + @Serializable(ByteStringBase64Serializer::class) val queryId: ByteString, + @Serializable(ByteStringBase64Serializer::class) override val data: ByteString ) : RldpMessage { override val id: ByteString diff --git a/tonapi-tl/src/rldp/RldpComplete.kt b/tonapi-tl/src/rldp/RldpComplete.kt index 32f7cc51..278204da 100644 --- a/tonapi-tl/src/rldp/RldpComplete.kt +++ b/tonapi-tl/src/rldp/RldpComplete.kt @@ -1,5 +1,6 @@ package org.ton.api.rldp +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.tl.* @@ -8,6 +9,7 @@ import org.ton.tl.* @SerialName("rldp.complete") public data class RldpComplete( @SerialName("transfer_id") + @Serializable(ByteStringBase64Serializer::class) override val transferId: ByteString, override val part: Int, ) : RldpMessagePart { diff --git a/tonapi-tl/src/rldp/RldpConfirm.kt b/tonapi-tl/src/rldp/RldpConfirm.kt index 2aa5ad36..4519adc4 100644 --- a/tonapi-tl/src/rldp/RldpConfirm.kt +++ b/tonapi-tl/src/rldp/RldpConfirm.kt @@ -1,5 +1,6 @@ package org.ton.api.rldp +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.tl.* @@ -8,6 +9,7 @@ import org.ton.tl.* @SerialName("rldp.confirm") public data class RldpConfirm( @SerialName("transfer_id") + @Serializable(ByteStringBase64Serializer::class) override val transferId: ByteString, override val part: Int, val seqno: Int diff --git a/tonapi-tl/src/rldp/RldpMessage.kt b/tonapi-tl/src/rldp/RldpMessage.kt index f2e1c272..d337a48a 100644 --- a/tonapi-tl/src/rldp/RldpMessage.kt +++ b/tonapi-tl/src/rldp/RldpMessage.kt @@ -2,10 +2,10 @@ package org.ton.api.rldp +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.Polymorphic import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonClassDiscriminator -import org.ton.tl.ByteString import org.ton.tl.TlCombinator import org.ton.tl.TlObject diff --git a/tonapi-tl/src/rldp/RldpMessageData.kt b/tonapi-tl/src/rldp/RldpMessageData.kt index 420261ba..49029c8a 100644 --- a/tonapi-tl/src/rldp/RldpMessageData.kt +++ b/tonapi-tl/src/rldp/RldpMessageData.kt @@ -1,5 +1,6 @@ package org.ton.api.rldp +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.tl.* @@ -7,7 +8,9 @@ import org.ton.tl.* @Serializable @SerialName("rldp.message") public data class RldpMessageData( + @Serializable(ByteStringBase64Serializer::class) override val id: ByteString, + @Serializable(ByteStringBase64Serializer::class) override val data: ByteString ) : RldpMessage { override fun tlCodec(): TlCodec = Companion diff --git a/tonapi-tl/src/rldp/RldpMessagePart.kt b/tonapi-tl/src/rldp/RldpMessagePart.kt index 808a6088..90a8f3ba 100644 --- a/tonapi-tl/src/rldp/RldpMessagePart.kt +++ b/tonapi-tl/src/rldp/RldpMessagePart.kt @@ -1,7 +1,7 @@ package org.ton.api.rldp +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.Serializable -import org.ton.tl.ByteString import org.ton.tl.TlCombinator import org.ton.tl.TlObject diff --git a/tonapi-tl/src/rldp/RldpMessagePartData.kt b/tonapi-tl/src/rldp/RldpMessagePartData.kt index 7cd9b6ab..69ebe713 100644 --- a/tonapi-tl/src/rldp/RldpMessagePartData.kt +++ b/tonapi-tl/src/rldp/RldpMessagePartData.kt @@ -1,5 +1,6 @@ package org.ton.api.rldp +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.fec.FecType @@ -10,6 +11,7 @@ import kotlin.jvm.JvmName @SerialName("rldp.messagePart") public data class RldpMessagePartData( @get:JvmName("transferId") + @Serializable(ByteStringBase64Serializer::class) override val transferId: ByteString, @SerialName("fec_type") @@ -27,6 +29,7 @@ public data class RldpMessagePartData( val seqno: Int, @get:JvmName("data") + @Serializable(ByteStringBase64Serializer::class) val data: ByteString ) : RldpMessagePart { override fun tlCodec(): TlCodec = Companion diff --git a/tonapi-tl/src/rldp/RldpQuery.kt b/tonapi-tl/src/rldp/RldpQuery.kt index a84c8963..b77c84cb 100644 --- a/tonapi-tl/src/rldp/RldpQuery.kt +++ b/tonapi-tl/src/rldp/RldpQuery.kt @@ -1,28 +1,22 @@ package org.ton.api.rldp -import kotlinx.datetime.Instant +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.tl.* -import org.ton.tl.ByteString.Companion.toByteString @Serializable @SerialName("rldp.query") public data class RldpQuery( @SerialName("query_id") + @Serializable(ByteStringBase64Serializer::class) val queryId: ByteString, @SerialName("max_answer_size") val maxAnswerSize: Long, val timeout: Int, + @Serializable(ByteStringBase64Serializer::class) override val data: ByteString ) : RldpMessage { - public constructor( - queryId: ByteArray, - maxAnswerSize: Long, - timeout: Instant, - data: ByteArray - ) : this(queryId.toByteString(), maxAnswerSize, timeout.epochSeconds.toInt(), data.toByteString()) - override val id: ByteString get() = queryId diff --git a/tonapi-tl/src/tcp/TcpAuthentificationComplete.kt b/tonapi-tl/src/tcp/TcpAuthentificationComplete.kt index d1227c71..eed5caac 100644 --- a/tonapi-tl/src/tcp/TcpAuthentificationComplete.kt +++ b/tonapi-tl/src/tcp/TcpAuthentificationComplete.kt @@ -1,5 +1,6 @@ package org.ton.api.tcp +import kotlinx.io.bytestring.ByteString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.api.pub.PublicKey @@ -9,22 +10,9 @@ import org.ton.tl.* @Serializable public data class TcpAuthentificationComplete( val key: PublicKey, - val signature: ByteArray + @Serializable(ByteStringBase64Serializer::class) + val signature: ByteString ) : TcpMessage { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is TcpAuthentificationComplete) return false - if (key != other.key) return false - if (!signature.contentEquals(other.signature)) return false - return true - } - - override fun hashCode(): Int { - var result = key.hashCode() - result = 31 * result + signature.contentHashCode() - return result - } - public companion object : TlCodec by TcpAuthentificationCompleteTlConstructor } @@ -33,7 +21,7 @@ private object TcpAuthentificationCompleteTlConstructor : TlConstructor by TcpAuthentificationNonceTlConstructor } @@ -28,7 +18,7 @@ private object TcpAuthentificationNonceTlConstructor : TlConstructor( diff --git a/tonapi-tl/src/tonnode/TonNodeBlockIdExt.kt b/tonapi-tl/src/tonnode/TonNodeBlockIdExt.kt index b74ea374..a2e84e59 100644 --- a/tonapi-tl/src/tonnode/TonNodeBlockIdExt.kt +++ b/tonapi-tl/src/tonnode/TonNodeBlockIdExt.kt @@ -2,11 +2,12 @@ package org.ton.api.tonnode +import kotlinx.io.bytestring.ByteString +import kotlinx.io.bytestring.hexToByteString +import kotlinx.io.bytestring.toHexString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.ton.tl.* -import org.ton.tl.ByteString.Companion.decodeFromHex -import org.ton.tl.ByteString.Companion.toByteString import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -26,36 +27,18 @@ public data class TonNodeBlockIdExt( @SerialName("root_hash") @get:JvmName("rootHash") + @Serializable(ByteStringBase64Serializer::class) val rootHash: ByteString, @SerialName("file_hash") @get:JvmName("fileHash") + @Serializable(ByteStringBase64Serializer::class) val fileHash: ByteString ) : TonNodeBlockId { - public constructor( - workchain: Int, - shard: Long, - seqno: Int, - rootHash: ByteArray, - fileHash: ByteArray - ) : this(workchain, shard, seqno, rootHash.toByteString(), fileHash.toByteString()) - - public constructor( - tonNodeBlockId: TonNodeBlockId, - rootHash: ByteArray, - fileHash: ByteArray, - ) : this( - tonNodeBlockId.workchain, - tonNodeBlockId.shard, - tonNodeBlockId.seqno, - rootHash, - fileHash - ) - public constructor( tonNodeBlockId: TonNodeBlockId = TonNodeBlockId(), - rootHash: ByteString = ByteString.of(*ByteArray(32)), - fileHash: ByteString = ByteString.of(*ByteArray(32)), + rootHash: ByteString = ByteString(*ByteArray(32)), + fileHash: ByteString = ByteString(*ByteArray(32)), ) : this( tonNodeBlockId.workchain, tonNodeBlockId.shard, @@ -68,14 +51,14 @@ public data class TonNodeBlockIdExt( append("(") append(workchain) append(":") - append(shard.toULong().toString(16).uppercase()) + append(shard.toULong().toHexString(HexFormat.UpperCase)) append(":") append(seqno) append(")") append(":") - append(rootHash.encodeHex()) + append(rootHash.toHexString(HexFormat.UpperCase)) append(":") - append(fileHash.encodeHex()) + append(fileHash.toHexString(HexFormat.UpperCase)) } public companion object : TlCodec by TonNodeBlockIdExtTlConstructor { @@ -87,7 +70,7 @@ public data class TonNodeBlockIdExt( val tonNodeBlockId = TonNodeBlockId.parse(string.substring(0, closeParenIndex + 1)) val hashes = string.substring(closeParenIndex + 2, string.lastIndex + 1) val (rawRootHash, rawFileHash) = hashes.split(':') - return TonNodeBlockIdExt(tonNodeBlockId, rawRootHash.decodeFromHex(), rawFileHash.decodeFromHex()) + return TonNodeBlockIdExt(tonNodeBlockId, rawRootHash.hexToByteString(), rawFileHash.hexToByteString()) } @JvmStatic @@ -107,8 +90,8 @@ private object TonNodeBlockIdExtTlConstructor : TlConstructor val workchain = reader.readInt() val shard = reader.readLong() val seqno = reader.readInt() - val rootHash = reader.readRaw(32) - val fileHash = reader.readRaw(32) + val rootHash = reader.readByteString(32) + val fileHash = reader.readByteString(32) return TonNodeBlockIdExt(workchain, shard, seqno, rootHash, fileHash) } @@ -116,7 +99,7 @@ private object TonNodeBlockIdExtTlConstructor : TlConstructor writer.writeInt(value.workchain) writer.writeLong(value.shard) writer.writeInt(value.seqno) - writer.writeRaw(value.rootHash.toByteArray()) - writer.writeRaw(value.fileHash.toByteArray()) + writer.writeRaw(value.rootHash) + writer.writeRaw(value.fileHash) } } diff --git a/tonapi-tl/src/tonnode/TonNodeZeroStateIdExt.kt b/tonapi-tl/src/tonnode/TonNodeZeroStateIdExt.kt index c30eaf9d..3a070ec6 100644 --- a/tonapi-tl/src/tonnode/TonNodeZeroStateIdExt.kt +++ b/tonapi-tl/src/tonnode/TonNodeZeroStateIdExt.kt @@ -2,11 +2,13 @@ package org.ton.api.tonnode +import kotlinx.io.bytestring.ByteString +import kotlinx.io.bytestring.toHexString import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers import org.ton.crypto.HexByteArraySerializer -import org.ton.tl.ByteString +import org.ton.tl.ByteStringBase64Serializer import org.ton.tl.TlConstructor import org.ton.tl.TlReader import org.ton.tl.TlWriter @@ -15,8 +17,10 @@ import org.ton.tl.TlWriter public data class TonNodeZeroStateIdExt( val workchain: Int, @SerialName("root_hash") + @Serializable(ByteStringBase64Serializer::class) val rootHash: ByteString, @SerialName("file_hash") + @Serializable(ByteStringBase64Serializer::class) val fileHash: ByteString ) { public constructor(tonNodeBlockIdExt: TonNodeBlockIdExt) : this( @@ -28,7 +32,8 @@ public data class TonNodeZeroStateIdExt( public fun isMasterchain(): Boolean = workchain == Workchain.MASTERCHAIN_ID public fun isValid(): Boolean = workchain != Workchain.INVALID_WORKCHAIN - override fun toString(): String = "($workchain:${rootHash}:${fileHash})" + override fun toString(): String = + "($workchain:${rootHash.toHexString(HexFormat.UpperCase)}:${fileHash.toHexString(HexFormat.UpperCase)})" public companion object : TlConstructor( schema = "tonNode.zeroStateIdExt workchain:int root_hash:int256 file_hash:int256 = tonNode.ZeroStateIdExt" diff --git a/tvm/src/cell/CellBuilder.kt b/tvm/src/cell/CellBuilder.kt index dd7b41e7..57c4ade0 100644 --- a/tvm/src/cell/CellBuilder.kt +++ b/tvm/src/cell/CellBuilder.kt @@ -360,14 +360,14 @@ private class CellBuilderImpl( } d1 = d1 and (CellDescriptor.LEVEL_MASK or CellDescriptor.HAS_HASHES_MASK).inv().toByte() d1 = d1 or (levelMask.mask shl 5).toByte() - hasher.writeByte(d1) - hasher.writeByte(d2) + hasher.updateByte(d1) + hasher.updateByte(d2) if (level == 0) { - hasher.write(data) + hasher.update(data) } else { val prevHash = hashes[level - 1].first - hasher.write(prevHash) + hasher.update(prevHash) } var depth = 0 @@ -375,13 +375,13 @@ private class CellBuilderImpl( val childDepth = child.depth(level + levelOffset) depth = max(depth, childDepth + 1) - hasher.writeByte((childDepth ushr Byte.SIZE_BITS).toByte()) - hasher.writeByte(childDepth.toByte()) + hasher.updateByte((childDepth ushr Byte.SIZE_BITS).toByte()) + hasher.updateByte(childDepth.toByte()) } refs.forEach { child -> val childHash = child.hash(level + levelOffset).toByteArray() - hasher.write(childHash) + hasher.update(childHash) } val hash = hasher.digest()