From c45e5ccf52d2f25516c80179b1c30fadd23d19ec Mon Sep 17 00:00:00 2001 From: Andrey Pfau Date: Sat, 21 Jan 2023 19:30:03 +0300 Subject: [PATCH] fix lookup block --- .../functions/LiteServerLookupBlock.kt | 36 ++----------- .../jvm/test/BlockSubscriberExample.kt | 50 +++++++++++++++++++ ton-kotlin-liteclient/jvm/test/test.kt | 33 ------------ .../kotlin/org/ton/lite/client/LiteClient.kt | 23 +++++++-- 4 files changed, 73 insertions(+), 69 deletions(-) create mode 100644 ton-kotlin-liteclient/jvm/test/BlockSubscriberExample.kt delete mode 100644 ton-kotlin-liteclient/jvm/test/test.kt diff --git a/ton-kotlin-liteapi/src/commonMain/kotlin/org/ton/lite/api/liteserver/functions/LiteServerLookupBlock.kt b/ton-kotlin-liteapi/src/commonMain/kotlin/org/ton/lite/api/liteserver/functions/LiteServerLookupBlock.kt index 38567f07..b23e0605 100644 --- a/ton-kotlin-liteapi/src/commonMain/kotlin/org/ton/lite/api/liteserver/functions/LiteServerLookupBlock.kt +++ b/ton-kotlin-liteapi/src/commonMain/kotlin/org/ton/lite/api/liteserver/functions/LiteServerLookupBlock.kt @@ -5,7 +5,6 @@ import kotlinx.serialization.Serializable import org.ton.api.tonnode.TonNodeBlockId import org.ton.lite.api.liteserver.LiteServerBlockHeader import org.ton.tl.* -import kotlin.jvm.JvmStatic @Serializable @SerialName("liteServer.lookupBlock") @@ -15,42 +14,13 @@ public data class LiteServerLookupBlock( val lt: Long?, val utime: Int? ) : TLFunction { - public constructor(id: TonNodeBlockId, lt: Long?, utime: Int?) : this( - mode( - lt != null, - utime != null - ), id, lt, utime - ) - - public constructor(id: TonNodeBlockId, lt: Long) : this(id, lt, null) - public constructor(id: TonNodeBlockId, utime: Int) : this(id, null, utime) - override fun tlCodec(): TlCodec = LiteServerLookupBlockTlConstructor override fun resultTlCodec(): TlCodec = LiteServerBlockHeader public companion object : TlCodec by LiteServerLookupBlockTlConstructor { - @JvmStatic - public fun mode( - hasLt: Boolean, - hasUtime: Boolean - ): Int { - var mode = 0 - if (hasLt) mode = mode or 1 - if (hasUtime) mode = mode or 2 - return mode - } - - @JvmStatic - public fun byTime( - id: TonNodeBlockId, - utime: Int - ): LiteServerLookupBlock = LiteServerLookupBlock(id, utime) - - @JvmStatic - public fun byLt( - id: TonNodeBlockId, - lt: Long - ): LiteServerLookupBlock = LiteServerLookupBlock(id, lt) + public const val ID_MASK: Int = 1 + public const val LT_MASK: Int = 2 + public const val UTIME_MASK: Int = 4 } } diff --git a/ton-kotlin-liteclient/jvm/test/BlockSubscriberExample.kt b/ton-kotlin-liteclient/jvm/test/BlockSubscriberExample.kt new file mode 100644 index 00000000..e2dd2a34 --- /dev/null +++ b/ton-kotlin-liteclient/jvm/test/BlockSubscriberExample.kt @@ -0,0 +1,50 @@ +import io.ktor.util.* +import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import org.ton.api.liteserver.LiteServerDesc +import org.ton.api.pub.PublicKeyEd25519 +import org.ton.api.tonnode.TonNodeBlockId +import org.ton.api.tonnode.TonNodeBlockIdExt +import org.ton.lite.client.LiteClient + +suspend fun main() { + val liteClient = LiteClient( + CoroutineName("liteClient"), + LiteServerDesc( + ip = 1091931625, + port = 30131, + id = PublicKeyEd25519("wrQaeIFispPfHndEBc0s0fx7GSp8UFFvebnytQQfc6A=".decodeBase64Bytes()) + ) + ) + + val mutableFlow = MutableStateFlow( + liteClient.getLastBlockId() + ) + GlobalScope.launch { + while (true) { + mutableFlow.update { + var block: TonNodeBlockIdExt? = null + while (block == null) { + block = liteClient.lookupBlock( + TonNodeBlockId( + it.workchain, + it.shard, + it.seqno + 1, + ) + ) + } + block + } + } + } + + val flow = mutableFlow.asStateFlow() + flow.collectLatest { + println(it) + } +} diff --git a/ton-kotlin-liteclient/jvm/test/test.kt b/ton-kotlin-liteclient/jvm/test/test.kt deleted file mode 100644 index 078eb749..00000000 --- a/ton-kotlin-liteclient/jvm/test/test.kt +++ /dev/null @@ -1,33 +0,0 @@ -import io.ktor.util.* -import kotlinx.coroutines.CoroutineName -import kotlinx.coroutines.delay -import org.ton.api.liteserver.LiteServerDesc -import org.ton.api.pub.PublicKeyEd25519 -import org.ton.api.tonnode.TonNodeBlockIdExt -import org.ton.lite.client.LiteClient - -suspend fun main() { - val liteClient = LiteClient( - CoroutineName("liteClient"), - LiteServerDesc( - ip = 1091931625, - port = 30131, - id = PublicKeyEd25519("wrQaeIFispPfHndEBc0s0fx7GSp8UFFvebnytQQfc6A=".decodeBase64Bytes()) - ) - ) - - var id: TonNodeBlockIdExt? = null - while (true) { - val currentId = liteClient.getLastBlockId() - if (currentId == id) { - delay(1000) - continue - } - id = currentId - println(currentId) - val block = liteClient.getBlock(id) - if (block != null) { - println(block.extra.account_blocks.value.nodes().map { it.first.account_addr }.toList()) - } - } -} diff --git a/ton-kotlin-liteclient/src/commonMain/kotlin/org/ton/lite/client/LiteClient.kt b/ton-kotlin-liteclient/src/commonMain/kotlin/org/ton/lite/client/LiteClient.kt index cd5fce0e..65ad9f85 100644 --- a/ton-kotlin-liteclient/src/commonMain/kotlin/org/ton/lite/client/LiteClient.kt +++ b/ton-kotlin-liteclient/src/commonMain/kotlin/org/ton/lite/client/LiteClient.kt @@ -23,6 +23,8 @@ import org.ton.cell.CellType import org.ton.crypto.crc16 import org.ton.crypto.sha256 import org.ton.lite.api.LiteApiClient +import org.ton.lite.api.exception.LiteServerNotReadyException +import org.ton.lite.api.exception.LiteServerUnknownException import org.ton.lite.api.liteserver.* import org.ton.lite.api.liteserver.functions.* import org.ton.logger.Logger @@ -241,15 +243,30 @@ public class LiteClient( if (knownBlockId != null) { return knownBlockId } + val mode = when { + time != null -> LiteServerLookupBlock.UTIME_MASK + lt != null -> LiteServerLookupBlock.LT_MASK + else -> LiteServerLookupBlock.ID_MASK + } val blockHeader = try { - liteApi(LiteServerLookupBlock(blockId, lt, time?.epochSeconds?.toInt())) - } catch (e: TonNotReadyException) { + liteApi(LiteServerLookupBlock(mode, blockId, lt, time?.epochSeconds?.toInt())) + } catch (e: LiteServerNotReadyException) { return null + } catch (e: LiteServerUnknownException) { + if (e.message == "block is not applied") { + return null + } else { + throw e + } } catch (e: Exception) { throw RuntimeException("Can't lookup block header for $blockId from server", e) } val actualBlockId = blockHeader.id - check((!blockId.isValid()) || blockId == actualBlockId) { + check( + blockId.workchain == actualBlockId.workchain && + blockId.shard == actualBlockId.shard && + blockId.seqno == actualBlockId.seqno + ) { "block id mismatch, expected: $blockId actual: $actualBlockId" } val blockProofCell = try {