From 014bfd83edf444e1ec92e339f6d7ddf3e4def240 Mon Sep 17 00:00:00 2001 From: neodiX Date: Sun, 4 Aug 2024 16:46:24 +0200 Subject: [PATCH] Tonlib builder now supports lite-server index - liteServerIndex(); Tonlib builder has a new parameter of type TonGlobalConfig, .globalConfig() - anyone can construct custom global.config now; Also in case of connection failure automatically tries to connect to other lite-servers from the list - WIP. --- .../org/ton/java/hashmaps/TestHashMap.java | 2 +- .../main/java/org/ton/java/tonlib/Tonlib.java | 106 ++++++++----- .../tonlib/types/globalconfig/AddrList.java | 26 ++++ .../tonlib/types/globalconfig/BlockInfo.java | 24 +++ .../java/tonlib/types/globalconfig/Dht.java | 24 +++ .../tonlib/types/globalconfig/DhtAddr.java | 23 +++ .../tonlib/types/globalconfig/DhtNode.java | 25 +++ .../tonlib/types/globalconfig/DhtNodeId.java | 22 +++ .../types/globalconfig/KeyStoreType.java | 5 + .../globalconfig/KeyStoreTypeDirectory.java | 23 +++ .../globalconfig/KeyStoreTypeMemory.java | 21 +++ .../types/globalconfig/LiteServerId.java | 22 +++ .../types/globalconfig/LiteServers.java | 22 +++ .../types/globalconfig/StaticNodes.java | 23 +++ .../types/globalconfig/TonGlobalConfig.java | 22 +++ .../types/globalconfig/TonlibConfig.java | 26 ++++ .../types/globalconfig/TonlibOptions.java | 24 +++ .../types/globalconfig/TonlibSetup.java | 20 +++ .../tonlib/types/globalconfig/Validator.java | 24 +++ .../org/ton/java/tonlib/TestTonlibJson.java | 146 ++++++++++++++++-- tonlib/src/test/resources/init.json | 14 -- .../test/resources/testnet-global.config.json | 69 +++++++++ .../main/java/org/ton/java/utils/Utils.java | 11 ++ .../java/org/ton/java/utils/TestUtils.java | 32 +++- 24 files changed, 691 insertions(+), 65 deletions(-) create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/AddrList.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/BlockInfo.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/Dht.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/DhtAddr.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/DhtNode.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/DhtNodeId.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/KeyStoreType.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/KeyStoreTypeDirectory.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/KeyStoreTypeMemory.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/LiteServerId.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/LiteServers.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/StaticNodes.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonGlobalConfig.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonlibConfig.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonlibOptions.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonlibSetup.java create mode 100644 tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/Validator.java delete mode 100644 tonlib/src/test/resources/init.json diff --git a/cell/src/test/java/org/ton/java/hashmaps/TestHashMap.java b/cell/src/test/java/org/ton/java/hashmaps/TestHashMap.java index b0ccdcdb..4565fd14 100644 --- a/cell/src/test/java/org/ton/java/hashmaps/TestHashMap.java +++ b/cell/src/test/java/org/ton/java/hashmaps/TestHashMap.java @@ -71,7 +71,7 @@ public void testHashMapSerialization() { log.info("serialized cell: \n{}", cell.print()); log.info("cell hash {}", Utils.bytesToHex(cell.hash())); - + log.info("cell hash ref0 {}", Utils.bytesToHex(cell.getRefs().get(0).hash())); log.info("cell hash ref1 {}", Utils.bytesToHex(cell.getRefs().get(1).hash())); diff --git a/tonlib/src/main/java/org/ton/java/tonlib/Tonlib.java b/tonlib/src/main/java/org/ton/java/tonlib/Tonlib.java index ffb891a4..21ba8932 100644 --- a/tonlib/src/main/java/org/ton/java/tonlib/Tonlib.java +++ b/tonlib/src/main/java/org/ton/java/tonlib/Tonlib.java @@ -2,7 +2,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonParser; import com.google.gson.ToNumberPolicy; import com.sun.jna.Native; import lombok.Builder; @@ -14,6 +13,7 @@ import org.ton.java.cell.CellBuilder; import org.ton.java.tonlib.queries.*; import org.ton.java.tonlib.types.*; +import org.ton.java.tonlib.types.globalconfig.*; import org.ton.java.utils.Utils; import java.io.InputStream; @@ -62,6 +62,8 @@ public class Tonlib { * if not specified and pathToGlobalConfig is filled then pathToGlobalConfig is used; */ private String globalConfigAsString; + + private TonGlobalConfig globalConfig; /** * Valid values are:
* 0 - FATAL
@@ -83,6 +85,8 @@ public class Tonlib { private String keystorePath; + private Integer liteServerIndex; + /** * Default value 5 */ @@ -98,9 +102,8 @@ public class Tonlib { private final long tonlib; - private boolean synced; - RunResultParser runResultParser; + LibraryResultParser libraryResultParser; public static class TonlibBuilder { @@ -151,6 +154,10 @@ public Tonlib build() { super.keystorePath = "."; } + if (isNull(super.liteServerIndex)) { + super.liteServerIndex = -1; + } + super.keystorePath = super.keystorePath.replace("\\", "/"); if (super.receiveRetryTimes == 0) { @@ -165,11 +172,10 @@ public Tonlib build() { super.ignoreCache = true; } - super.synced = false; super.runResultParser = new RunResultParser(); super.libraryResultParser = new LibraryResultParser(); - String configData; + String originalGlobalConfig; if (isNull(super.pathToGlobalConfig)) { if (isNull(super.globalConfigAsString)) { @@ -181,22 +187,36 @@ public Tonlib build() { super.pathToGlobalConfig = "global-config.json (integrated resource)"; config = Tonlib.class.getClassLoader().getResourceAsStream("global-config.json"); } - configData = Utils.streamToString(config); + originalGlobalConfig = Utils.streamToString(config); if (nonNull(config)) { config.close(); } } else { - configData = super.globalConfigAsString; + originalGlobalConfig = super.globalConfigAsString; } + } else if (nonNull(super.globalConfig)) { + originalGlobalConfig = gson.toJson(super.globalConfig); } else { if (Files.exists(Paths.get(super.pathToGlobalConfig))) { - configData = new String(Files.readAllBytes(Paths.get(super.pathToGlobalConfig))); + originalGlobalConfig = new String(Files.readAllBytes(Paths.get(super.pathToGlobalConfig))); } else { throw new RuntimeException("Global config is not found in path: " + super.pathToGlobalConfig); } } + TonGlobalConfig globalConfigInternal = gson.fromJson(originalGlobalConfig, TonGlobalConfig.class); + + if (super.liteServerIndex != -1) { + if (super.liteServerIndex > globalConfigInternal.getLiteservers().length - 1) { + throw new RuntimeException("Specified lite-server index is greater than total number of lite-servers in config."); + } + LiteServers[] liteServers = globalConfigInternal.getLiteservers(); + LiteServers[] newLiteServers = new LiteServers[1]; + newLiteServers[0] = liteServers[super.liteServerIndex]; + globalConfigInternal.setLiteservers(newLiteServers); + } + super.tonlibJson = Native.load(super.pathToTonlibSharedLib, TonlibJsonI.class); super.tonlib = super.tonlibJson.tonlib_client_json_create(); @@ -207,6 +227,10 @@ public Tonlib build() { "Keystore path: %s\n" + "Path to global config: %s\n" + "Global config as string: %s\n" + + "lite-servers found: %s\n" + + "dht-nodes found: %s\n" + + "init-block seqno: %s\n" + + "%s\n" + "Ignore cache: %s\n" + "Testnet: %s\n" + "Receive timeout: %s seconds\n" + @@ -219,50 +243,60 @@ public Tonlib build() { super.pathToGlobalConfig, (super.globalConfigAsString != null && super.globalConfigAsString.length() > 33) ? super.globalConfigAsString.substring(0, 33) : "", + globalConfigInternal.getLiteservers().length, + globalConfigInternal.getDht().getStatic_nodes().getNodes().length, + globalConfigInternal.getValidator().getInit_block().getSeqno(), + (super.liteServerIndex == -1) ? "using lite-servers: all" : "using lite-server at index: " + super.liteServerIndex + " (" + Utils.int2ip(globalConfigInternal.getLiteservers()[0].getIp()) + ")", super.ignoreCache, super.testnet, super.receiveTimeout, super.receiveRetryTimes); + // set verbosity VerbosityLevelQuery verbosityLevelQuery = VerbosityLevelQuery.builder().new_verbosity_level(super.verbosityLevel.ordinal()).build(); - super.tonlibJson.tonlib_client_json_send(super.tonlib, gson.toJson(verbosityLevelQuery)); + super.tonlibJson.tonlib_client_json_receive(super.tonlib, super.receiveTimeout); - String result = super.tonlibJson.tonlib_client_json_receive(super.tonlib, super.receiveTimeout); - System.out.println("set verbosityLevel result: " + result); - - String initTemplate = Utils.streamToString(Tonlib.class.getClassLoader().getResourceAsStream("init.json")); - - String dataQuery = JsonParser.parseString(configData).getAsJsonObject().toString(); - - String q = initTemplate.replace("CFG_PLACEHOLDER", dataQuery); - q = q.replace("IGNORE_CACHE", super.ignoreCache.toString()); - if (super.keystoreInMemory) { - String keystoreMemory = " 'keystore_type': { '@type': 'keyStoreTypeInMemory' }"; - q = q.replace("KEYSTORE_TYPE", keystoreMemory); - } else { - String keystoreDirectory = "'keystore_type': {'@type': 'keyStoreTypeDirectory', 'directory': '.' } "; - if (super.keystorePath.equals(".")) { - q = q.replace("KEYSTORE_TYPE", keystoreDirectory); - } else { - q = q.replace("KEYSTORE_TYPE", keystoreDirectory.replace(".", super.keystorePath)); - } - } - - String setupQueryQ = JsonParser.parseString(q).getAsJsonObject().toString(); - - super.tonlibJson.tonlib_client_json_send(super.tonlib, setupQueryQ); - - result = super.tonlibJson.tonlib_client_json_receive(super.tonlib, super.receiveTimeout); - System.out.println("set tonlib configuration result " + result); + initTonlibConfig(globalConfigInternal); } catch (Exception e) { throw new RuntimeException("Error creating tonlib instance: " + e.getMessage()); } return super.build(); } + + private void initTonlibConfig(TonGlobalConfig tonGlobalConfig) { + + TonlibSetup tonlibSetup = TonlibSetup.builder() + .type("init") + .options(TonlibOptions.builder() + .type("options") + .config(TonlibConfig.builder() + .type("config") + .config(gson.toJson(tonGlobalConfig)) + .use_callbacks_for_network(false) + .blockchain_name("") + .ignore_cache(true) + .build()) + .keystore_type( + super.keystoreInMemory ? + KeyStoreTypeMemory.builder() + .type("keyStoreTypeInMemory") + .build() + : + KeyStoreTypeDirectory.builder() + .type("keyStoreTypeDirectory") + .directory(super.keystorePath.equals(".") ? "." : super.keystorePath) + .build()) + .build()) + .build(); + + super.tonlibJson.tonlib_client_json_send(super.tonlib, gson.toJson(tonlibSetup)); + super.tonlibJson.tonlib_client_json_receive(super.tonlib, super.receiveTimeout); + } } + public void destroy() { tonlibJson.tonlib_client_json_destroy(tonlib); } diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/AddrList.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/AddrList.java new file mode 100644 index 00000000..5dc6c891 --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/AddrList.java @@ -0,0 +1,26 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class AddrList { + @SerializedName(value = "@type") + String type; + DhtAddr[] addrs; + long version; + long reinit_date; + long priority; + long expire_at; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/BlockInfo.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/BlockInfo.java new file mode 100644 index 00000000..75383b6b --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/BlockInfo.java @@ -0,0 +1,24 @@ +package org.ton.java.tonlib.types.globalconfig; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class BlockInfo { + + private String file_hash; + private String root_hash; + private long seqno; + private long workchain; + private long shard; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/Dht.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/Dht.java new file mode 100644 index 00000000..c8ca624a --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/Dht.java @@ -0,0 +1,24 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class Dht { + @SerializedName(value = "@type") + String type; + int a; + int k; + StaticNodes static_nodes; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/DhtAddr.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/DhtAddr.java new file mode 100644 index 00000000..c2aebce9 --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/DhtAddr.java @@ -0,0 +1,23 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class DhtAddr { + @SerializedName(value = "@type") + String type; + long ip; + long port; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/DhtNode.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/DhtNode.java new file mode 100644 index 00000000..f0bdc425 --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/DhtNode.java @@ -0,0 +1,25 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class DhtNode { + @SerializedName(value = "@type") + String type; + DhtNodeId id; + AddrList addr_list; + long version; + String signature; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/DhtNodeId.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/DhtNodeId.java new file mode 100644 index 00000000..c31819ed --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/DhtNodeId.java @@ -0,0 +1,22 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class DhtNodeId { + @SerializedName(value = "@type") + String type; + String key; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/KeyStoreType.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/KeyStoreType.java new file mode 100644 index 00000000..7dd8bf19 --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/KeyStoreType.java @@ -0,0 +1,5 @@ +package org.ton.java.tonlib.types.globalconfig; + +public interface KeyStoreType { + +} \ No newline at end of file diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/KeyStoreTypeDirectory.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/KeyStoreTypeDirectory.java new file mode 100644 index 00000000..ca999831 --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/KeyStoreTypeDirectory.java @@ -0,0 +1,23 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class KeyStoreTypeDirectory implements KeyStoreType { + @SerializedName(value = "@type") + String type; + + String directory; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/KeyStoreTypeMemory.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/KeyStoreTypeMemory.java new file mode 100644 index 00000000..c4573660 --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/KeyStoreTypeMemory.java @@ -0,0 +1,21 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class KeyStoreTypeMemory implements KeyStoreType { + @SerializedName(value = "@type") + String type; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/LiteServerId.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/LiteServerId.java new file mode 100644 index 00000000..86759dda --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/LiteServerId.java @@ -0,0 +1,22 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class LiteServerId { + @SerializedName(value = "@type") + String type; + String key; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/LiteServers.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/LiteServers.java new file mode 100644 index 00000000..328bb29f --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/LiteServers.java @@ -0,0 +1,22 @@ +package org.ton.java.tonlib.types.globalconfig; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class LiteServers { + private long ip; + private long port; + private String provided; + private LiteServerId id; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/StaticNodes.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/StaticNodes.java new file mode 100644 index 00000000..1ca7b037 --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/StaticNodes.java @@ -0,0 +1,23 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class StaticNodes { + @SerializedName(value = "@type") + String type; + + DhtNode[] nodes; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonGlobalConfig.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonGlobalConfig.java new file mode 100644 index 00000000..f47d9f98 --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonGlobalConfig.java @@ -0,0 +1,22 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; + +@Builder +@Getter +@Setter +@ToString +public class TonGlobalConfig implements Serializable { + @SerializedName(value = "@type") + String type; + + LiteServers[] liteservers; + Validator validator; + Dht dht; +} diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonlibConfig.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonlibConfig.java new file mode 100644 index 00000000..d55a811f --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonlibConfig.java @@ -0,0 +1,26 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class TonlibConfig { + @SerializedName(value = "@type") + String type; + + String config; + boolean use_callbacks_for_network; + String blockchain_name; + boolean ignore_cache; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonlibOptions.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonlibOptions.java new file mode 100644 index 00000000..472e6a71 --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonlibOptions.java @@ -0,0 +1,24 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class TonlibOptions { + @SerializedName(value = "@type") + String type; + + TonlibConfig config; + KeyStoreType keystore_type; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonlibSetup.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonlibSetup.java new file mode 100644 index 00000000..a10d2f9b --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/TonlibSetup.java @@ -0,0 +1,20 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; + +@Builder +@Getter +@Setter +@ToString +public class TonlibSetup implements Serializable { + @SerializedName(value = "@type") + String type; + + TonlibOptions options; +} diff --git a/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/Validator.java b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/Validator.java new file mode 100644 index 00000000..e921d646 --- /dev/null +++ b/tonlib/src/main/java/org/ton/java/tonlib/types/globalconfig/Validator.java @@ -0,0 +1,24 @@ +package org.ton.java.tonlib.types.globalconfig; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +@Builder +@Setter +@Getter +public class Validator { + @SerializedName(value = "@type") + String type; + BlockInfo[] hardforks; + BlockInfo zero_state; + BlockInfo init_block; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} \ No newline at end of file diff --git a/tonlib/src/test/java/org/ton/java/tonlib/TestTonlibJson.java b/tonlib/src/test/java/org/ton/java/tonlib/TestTonlibJson.java index 4ba08b71..404631d8 100644 --- a/tonlib/src/test/java/org/ton/java/tonlib/TestTonlibJson.java +++ b/tonlib/src/test/java/org/ton/java/tonlib/TestTonlibJson.java @@ -2,10 +2,10 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonParser; import com.iwebpp.crypto.TweetNaclFast; import com.sun.jna.Native; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.junit.BeforeClass; import org.junit.Test; @@ -18,6 +18,7 @@ import org.ton.java.mnemonic.Mnemonic; import org.ton.java.tlb.types.ConfigParams8; import org.ton.java.tonlib.types.*; +import org.ton.java.tonlib.types.globalconfig.*; import org.ton.java.utils.Utils; import java.io.IOException; @@ -25,7 +26,10 @@ import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.*; +import java.util.ArrayDeque; +import java.util.Collections; +import java.util.Deque; +import java.util.Map; import static java.util.Objects.nonNull; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -38,14 +42,12 @@ public class TestTonlibJson { public static final String TON_FOUNDATION = "EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N"; public static final String ELECTOR_ADDRESSS = "-1:3333333333333333333333333333333333333333333333333333333333333333"; - public String INIT_TEMPLATE = Utils.streamToString(Objects.requireNonNull(TestTonlibJson.class.getClassLoader().getResourceAsStream("init.json"))); - Gson gs = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); static Tonlib tonlib; @BeforeClass - public static void setUpBeforeClass() throws Exception { + public static void setUpBeforeClass() { tonlib = Tonlib.builder().ignoreCache(false).build(); } @@ -66,22 +68,140 @@ public void testInitTonlibJson() throws IOException { assert nonNull(testConfig); - String data = Utils.streamToString(testConfig); + String globalConfigJson = Utils.streamToString(testConfig); testConfig.close(); - assert nonNull(data); - - String dataQuery = JsonParser.parseString(data).getAsJsonObject().toString(); + assert nonNull(globalConfigJson); + + TonlibSetup tonlibSetup = TonlibSetup.builder() + .type("init") + .options(TonlibOptions.builder() + .type("options") + .config(TonlibConfig.builder() + .type("config") + .config(globalConfigJson) + .use_callbacks_for_network(false) + .blockchain_name("") + .ignore_cache(true) + .build()) + .keystore_type( + KeyStoreTypeDirectory.builder() + .type("keyStoreTypeDirectory") + .directory(".") + .build()) + .build()) + .build(); - String q = INIT_TEMPLATE.replace("CFG_PLACEHOLDER", dataQuery).replace("KEYSTORE_TYPE", KEYSTORE_MEMORY); - q = q.replace("IGNORE_CACHE", "true"); - String setupQueryQ = JsonParser.parseString(q).getAsJsonObject().toString(); - tonlibJson.tonlib_client_json_send(tonlib, setupQueryQ); + tonlibJson.tonlib_client_json_send(tonlib, gs.toJson(tonlibSetup)); String result = tonlibJson.tonlib_client_json_receive(tonlib, 10.0); assertThat(result).isNotBlank(); } + @Test + public void testGlobalConfigJsonParser() throws IOException { + + InputStream testConfig = TestTonlibJson.class.getClassLoader().getResourceAsStream("testnet-global.config.json"); + String configStr = Utils.streamToString(testConfig); + assert testConfig != null; + testConfig.close(); + TonGlobalConfig globalConfig = gs.fromJson(configStr, TonGlobalConfig.class); + log.info("config object: {}", globalConfig); + + log.info("lite-servers found {}", globalConfig.getLiteservers().length); + log.info("dht-servers found {}", globalConfig.getDht().getStatic_nodes().getNodes().length); + log.info("hard-forks found {}", globalConfig.getValidator().getHardforks().length); + + log.info("parsed config object back to json {}", gs.toJson(globalConfig)); + + Tonlib tonlib1 = Tonlib.builder() + .globalConfigAsString(gs.toJson(globalConfig)) + .ignoreCache(false) + .build(); + + log.info("last {}", tonlib1.getLast()); + } + + @Test + public void testManualGlobalConfig() { + + TonGlobalConfig testnetGlobalConfig = TonGlobalConfig.builder() + .liteservers(ArrayUtils.toArray( + LiteServers.builder() + .ip(1495755568) + .port(4695) + .id(LiteServerId.builder() + .type("pub.ed25519") + .key("cZpMFqy6n0Lsu8x/z2Jq0wh/OdM1WAVJJKSb2CvDECQ=") + .build()) + .build(), + LiteServers.builder() + .ip(1468571697) + .port(27787) + .id(LiteServerId.builder() + .type("pub.ed25519") + .key("Y/QVf6G5VDiKTZOKitbFVm067WsuocTN8Vg036A4zGk=") + .build()) + .build())) + .validator(Validator.builder() + .type("validator.config.global") + .zero_state(BlockInfo.builder() + .file_hash("Z+IKwYS54DmmJmesw/nAD5DzWadnOCMzee+kdgSYDOg=") + .root_hash("gj+B8wb/AmlPk1z1AhVI484rhrUpgSr2oSFIh56VoSg=") + .workchain(-1) + .seqno(0) + .shard(-9223372036854775808L) + .build()) + .hardforks(ArrayUtils.toArray( + BlockInfo.builder() + .file_hash("jF3RTD+OyOoP+OI9oIjdV6M8EaOh9E+8+c3m5JkPYdg=") + .root_hash("6JSqIYIkW7y8IorxfbQBoXiuY3kXjcoYgQOxTJpjXXA=") + .workchain(-1) + .seqno(5141579) + .shard(-9223372036854775808L) + .build(), + BlockInfo.builder() + .file_hash("WrNoMrn5UIVPDV/ug/VPjYatvde8TPvz5v1VYHCLPh8=") + .root_hash("054VCNNtUEwYGoRe1zjH+9b1q21/MeM+3fOo76Vcjes=") + .workchain(-1) + .seqno(5172980) + .shard(-9223372036854775808L) + .build(), + BlockInfo.builder() + .file_hash("xRaxgUwgTXYFb16YnR+Q+VVsczLl6jmYwvzhQ/ncrh4=") + .root_hash("SoPLqMe9Dz26YJPOGDOHApTSe5i0kXFtRmRh/zPMGuI=") + .workchain(-1) + .seqno(5176527) + .shard(-9223372036854775808L) + .build() + )).build()) + .build(); + log.info("config object: {}", testnetGlobalConfig); + + log.info("lite-servers found {}", testnetGlobalConfig.getLiteservers().length); + + log.info("parsed config object back to json {}", gs.toJson(testnetGlobalConfig)); + + Tonlib tonlib1 = Tonlib.builder() + .globalConfig(testnetGlobalConfig) + .ignoreCache(false) + .build(); + + log.info("last {}", tonlib1.getLast()); + } + + @Test + public void testTonlibUsingGlobalConfigLiteServerByIndex() { + + Tonlib tonlib1 = Tonlib.builder() + .ignoreCache(false) + .testnet(true) + .liteServerIndex(1) + .build(); + + log.info("last {}", tonlib1.getLast()); + } + @Test public void testTonlib() { Tonlib tonlib = Tonlib.builder() diff --git a/tonlib/src/test/resources/init.json b/tonlib/src/test/resources/init.json deleted file mode 100644 index 9ec3784f..00000000 --- a/tonlib/src/test/resources/init.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - '@type': 'init', - 'options': { - '@type': 'options', - 'config': { - '@type': 'config', - 'config': 'CFG_PLACEHOLDER', - 'use_callbacks_for_network': false, - 'blockchain_name': '', - 'ignore_cache': IGNORE_CACHE - }, - KEYSTORE_TYPE - } -} \ No newline at end of file diff --git a/tonlib/src/test/resources/testnet-global.config.json b/tonlib/src/test/resources/testnet-global.config.json index abd4a35b..328c91c0 100644 --- a/tonlib/src/test/resources/testnet-global.config.json +++ b/tonlib/src/test/resources/testnet-global.config.json @@ -1,5 +1,29 @@ { "liteservers": [ + { + "ip": 1592601963, + "port": 13833, + "id": { + "@type": "pub.ed25519", + "key": "QpVqQiv1u3nCHuBR3cg3fT6NqaFLlnLGbEgtBRukDpU=" + } + }, + { + "ip": 1162057690, + "port": 35939, + "id": { + "@type": "pub.ed25519", + "key": "97y55AkdzXWyyVuOAn+WX6p66XTNs2hEGG0jFUOkCIo=" + } + }, + { + "ip": -1304477830, + "port": 20700, + "id": { + "@type": "pub.ed25519", + "key": "dGLlRRai3K9FGkI0dhABmFHMv+92QEVrvmTrFf5fbqA=" + } + }, { "ip": 1495755568, "port": 4695, @@ -7,6 +31,51 @@ "@type": "pub.ed25519", "key": "cZpMFqy6n0Lsu8x/z2Jq0wh/OdM1WAVJJKSb2CvDECQ=" } + }, + { + "ip": -1468571697, + "port": 27787, + "provided": "Beavis", + "id": { + "@type": "pub.ed25519", + "key": "Y/QVf6G5VDiKTZOKitbFVm067WsuocTN8Vg036A4zGk=" + } + }, + { + "ip": -1468575011, + "port": 51088, + "provided": "Beavis", + "id": { + "@type": "pub.ed25519", + "key": "Sy5ghr3EahQd/1rDayzZXt5+inlfF+7kLfkZDJcU/ek=" + } + }, + { + "ip": 1844203537, + "port": 37537, + "provided": "Neo", + "id": { + "@type": "pub.ed25519", + "key": "K1F7zEe0ETf+SwkefLS56hJE8x42sjCVsBJJuaY7nEA=" + } + }, + { + "ip": 1844203589, + "port": 34411, + "provided": "Neo", + "id": { + "@type": "pub.ed25519", + "key": "pOpRRpIxDuMRm1qFUPpvVjD62vo8azkO0npw4FPcW/I=" + } + }, + { + "ip": 1047529523, + "port": 37649, + "provided": "Neo", + "id": { + "@type": "pub.ed25519", + "key": "pRf2sAa7d+Chl8gDclWOMtthtxjKnLYeAIzk869mMvA=" + } } ], "dht": { diff --git a/utils/src/main/java/org/ton/java/utils/Utils.java b/utils/src/main/java/org/ton/java/utils/Utils.java index 9f1b0eed..ee97acac 100644 --- a/utils/src/main/java/org/ton/java/utils/Utils.java +++ b/utils/src/main/java/org/ton/java/utils/Utils.java @@ -811,6 +811,17 @@ public static int ip2int(String address) { return result; } + public static String int2ip(long ip) { + if ((ip < 0) && (ip + Math.pow(2, 32) > Math.pow(2, 31))) { + ip = (long) (ip + Math.pow(2, 32)); + } + return ((ip >> 24) & 0xFF) + "." + + ((ip >> 16) & 0xFF) + "." + + ((ip >> 8) & 0xFF) + "." + + (ip & 0xFF); + + } + public static int[] reverseIntArray(int[] in) { int[] temp = in.clone(); for (int i = 0; i < temp.length / 2; i++) { diff --git a/utils/src/test/java/org/ton/java/utils/TestUtils.java b/utils/src/test/java/org/ton/java/utils/TestUtils.java index 61746bf2..6af6c4cb 100644 --- a/utils/src/test/java/org/ton/java/utils/TestUtils.java +++ b/utils/src/test/java/org/ton/java/utils/TestUtils.java @@ -12,6 +12,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.Assert.assertThrows; import static org.ton.java.utils.Utils.getCRC32ChecksumAsLong; +import static org.ton.java.utils.Utils.int2ip; @RunWith(JUnit4.class) @Slf4j @@ -320,7 +321,36 @@ public void testNanoFail() { @Test public void testReverseLong() { long l = 0x27e7c64a; - log.info("reversed " + Long.toHexString(Long.reverseBytes(l))); + log.info("reversed {}", Long.toHexString(Long.reverseBytes(l))); + } + + /** + * bash + * IP=185.86.79.9; + * IPNUM=0; for (( i=0 ; i<4 ; ++i )); do ((IPNUM=$IPNUM+${IP%%.*}*$((256**$((3-${i})))))); IP=${IP#*.}; done + * [ $IPNUM -gt $((2**31)) ] && IPNUM=$(($IPNUM - $((2**32)))) + * echo $IPNUM + */ + @Test + public void testLongIpToString() { + long ip = 1495755568; + log.info("ip {}", int2ip(ip)); + assertThat(int2ip(ip)).isEqualTo("89.39.107.48"); + + ip = -1062731775; + log.info("ip {}", int2ip(ip)); + + ip = -1185526007; + log.info("ip {}", int2ip(ip)); + assertThat(int2ip(ip)).isEqualTo("185.86.79.9"); + + ip = -1952265919; + log.info("ip {}", int2ip(ip)); + assertThat(int2ip(ip)).isEqualTo("139.162.201.65"); + + ip = -1468571697; + log.info("ip {}", int2ip(ip)); + assertThat(int2ip(ip)).isEqualTo("168.119.95.207"); } }