diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..dbcae6ab --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.github/workflows/ubuntu-18.04-compile.yml b/.github/workflows/ubuntu-18.04-compile.yml new file mode 100644 index 00000000..e215c7bd --- /dev/null +++ b/.github/workflows/ubuntu-18.04-compile.yml @@ -0,0 +1,40 @@ +name: C/C++ CI Ubuntu 18.04 Compile + +on: [push,workflow_dispatch] + +jobs: + build: + + runs-on: ubuntu-18.04 + + steps: + - name: Check out repository + uses: actions/checkout@v2 + with: + submodules: 'recursive' + + - name: Install libraries + run: | + sudo apt update + sudo apt install -y build-essential git make cmake clang libgflags-dev zlib1g-dev libssl-dev libreadline-dev libmicrohttpd-dev pkg-config libgsl-dev python3 python3-dev ninja-build + + - name: Configure & Build + run: | + export CC=$(which clang) + export CXX=$(which clang++) + export CCACHE_DISABLE=1 + mkdir build + cd build + cmake -GNinja -DCMAKE_BUILD_TYPE=Release .. + ninja fift func tonlib tonlibjson tonlib-cli validator-engine lite-client pow-miner validator-engine-console generate-random-id json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork + + - name: find & copy binaries + run: | + mkdir artifacts + cp build/crypto/fift build/crypto/tlbc build/crypto/func build/crypto/create-state build/validator-engine-console/validator-engine-console build/tonlib/tonlib-cli build/tonlib/libtonlibjson.so.0.5 build/http/http-proxy build/rldp-http-proxy/rldp-http-proxy build/dht-server/dht-server build/lite-client/lite-client build/validator-engine/validator-engine build/utils/generate-random-id build/utils/json2tlo build/adnl/adnl-proxy artifacts + + - name: Upload artifacts + uses: actions/upload-artifact@master + with: + name: ton-binaries + path: artifacts diff --git a/CMakeLists.txt b/CMakeLists.txt index d8f9deb3..44dbae8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,6 +101,14 @@ option(TON_USE_TSAN "Use \"ON\" to enable ThreadSanitizer." OFF) option(TON_USE_UBSAN "Use \"ON\" to enable UndefinedBehaviorSanitizer." OFF) set(TON_ARCH "native" CACHE STRING "Architecture, will be passed to -march=") +#BEGIN M1 support +EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE ARCHITECTURE ) + +if ((ARCHITECTURE MATCHES "arm64") AND (CMAKE_SYSTEM_NAME STREQUAL "Darwin")) + set(TON_ARCH "apple-m1") +endif() +#END M1 support + if (TON_USE_ABSEIL) message("Add abseil-cpp") set(ABSL_PROPAGATE_CXX_STD TRUE) @@ -189,7 +197,11 @@ find_package(Threads REQUIRED) find_package(ZLIB REQUIRED) if (TON_ARCH AND NOT MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${TON_ARCH}") + if (TON_ARCH STREQUAL "apple-m1") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=${TON_ARCH}") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${TON_ARCH}") + endif() endif() if (THREADS_HAVE_PTHREAD_ARG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") @@ -550,4 +562,3 @@ add_test(test-tddb test-tddb ${TEST_OPTIONS}) add_test(test-db test-db ${TEST_OPTIONS}) endif() #END internal - diff --git a/crypto/block/block.tlb b/crypto/block/block.tlb index b970d919..46b29cf2 100644 --- a/crypto/block/block.tlb +++ b/crypto/block/block.tlb @@ -807,7 +807,7 @@ vmc_pushint$1111 value:int32 next:^VmCont = VmCont; // // DNS RECORDS // -_ (HashmapE 16 ^DNSRecord) = DNS_RecordSet; +_ (HashmapE 256 DNSRecord) = DNS_RecordSet; chunk_ref$_ {n:#} ref:^(TextChunks (n + 1)) = TextChunkRef (n + 1); chunk_ref_empty$_ = TextChunkRef 0; diff --git a/crypto/smc-envelope/ManualDns.cpp b/crypto/smc-envelope/ManualDns.cpp index 00f1becb..8f5097c0 100644 --- a/crypto/smc-envelope/ManualDns.cpp +++ b/crypto/smc-envelope/ManualDns.cpp @@ -146,24 +146,27 @@ td::Result DnsInterface::EntryData::from_cellslice(vm:: return td::Status::Error("Unknown entry data"); } -SmartContract::Args DnsInterface::resolve_args_raw(td::Slice encoded_name, td::int16 category) { +SmartContract::Args DnsInterface::resolve_args_raw(td::Slice encoded_name, td::Bits256 category, + block::StdAddress address) { SmartContract::Args res; res.set_method_id("dnsresolve"); res.set_stack( - {vm::load_cell_slice_ref(vm::CellBuilder().store_bytes(encoded_name).finalize()), td::make_refint(category)}); + {vm::load_cell_slice_ref(vm::CellBuilder().store_bytes(encoded_name).finalize()), + td::bits_to_refint(category.cbits(), 256, false)}); + res.set_address(std::move(address)); return res; } -td::Result DnsInterface::resolve_args(td::Slice name, td::int32 category_big) { - TRY_RESULT(category, td::narrow_cast_safe(category_big)); +td::Result DnsInterface::resolve_args(td::Slice name, td::Bits256 category, + block::StdAddress address) { if (name.size() > get_default_max_name_size()) { return td::Status::Error("Name is too long"); } auto encoded_name = encode_name(name); - return resolve_args_raw(encoded_name, category); + return resolve_args_raw(encoded_name, category, std::move(address)); } -td::Result> DnsInterface::resolve(td::Slice name, td::int32 category) const { +td::Result> DnsInterface::resolve(td::Slice name, td::Bits256 category) const { TRY_RESULT(raw_entries, resolve_raw(name, category)); std::vector entries; entries.reserve(raw_entries.size()); @@ -171,10 +174,15 @@ td::Result> DnsInterface::resolve(td::Slice nam Entry entry; entry.name = std::move(raw_entry.name); entry.category = raw_entry.category; - auto cs = vm::load_cell_slice(raw_entry.data); - TRY_RESULT(data, EntryData::from_cellslice(cs)); - entry.data = std::move(data); - entries.push_back(std::move(entry)); + entry.partially_resolved = raw_entry.partially_resolved; + auto cs = *raw_entry.data; + auto data = EntryData::from_cellslice(cs); + if (data.is_error()) { + LOG(INFO) << "Failed to parse DNS entry: " << data.move_as_error(); + } else { + entry.data = data.move_as_ok(); + entries.push_back(std::move(entry)); + } } return entries; } @@ -188,9 +196,9 @@ td::Result> DnsInterface::resolve(td::Slice nam Inline [Name] structure: [UInt<6b>:length] [Bytes:data] Operations (continuation of message): 00 Contract initialization message (only if seqno = 0) (x=-) - 31 TSet: replace ENTIRE DOMAIN TABLE with the provided tree root cell (x=-) + 31 TSet: replace ENTIRE DOMAIN TABLE with the provided tree root cell (x=-) [Cell<1r>:new_domains_table] - 51 OSet: replace owner public key with a new one (x=-) + 51 OSet: replace owner public key with a new one (x=-) [UInt<256b>:new_public_key] */ // creation @@ -233,37 +241,37 @@ td::Result ManualDns::get_wallet_id_or_throw() const { return static_cast(vm::load_cell_slice(state_.data).fetch_ulong(32)); } -td::Result> ManualDns::create_set_value_unsigned(td::int16 category, td::Slice name, +td::Result> ManualDns::create_set_value_unsigned(td::Bits256 category, td::Slice name, td::Ref data) const { //11 VSet: set specified value to specified subdomain->category (x=2) - //[Int<16b>:category] [Name:subdomain] [Cell<1r>:value] + //[Int<256b>:category] [Name:subdomain] [Cell<1r>:value] vm::CellBuilder cb; cb.store_long(11, 6); - if (name.size() <= 58 - 2) { - cb.store_long(category, 16); + if (name.size() <= 58 - 32) { + cb.store_bytes(category.as_slice()); cb.store_long(0, 1); cb.store_long(name.size(), 6); cb.store_bytes(name); } else { - cb.store_long(category, 16); + cb.store_bytes(category.as_slice()); cb.store_long(1, 1); cb.store_ref(vm::CellBuilder().store_bytes(name).finalize()); } cb.store_maybe_ref(std::move(data)); return cb.finalize(); } -td::Result> ManualDns::create_delete_value_unsigned(td::int16 category, td::Slice name) const { +td::Result> ManualDns::create_delete_value_unsigned(td::Bits256 category, td::Slice name) const { //12 VDel: delete specified subdomain->category (x=2) - //[Int<16b>:category] [Name:subdomain] + //[Int<256b>:category] [Name:subdomain] vm::CellBuilder cb; cb.store_long(12, 6); - if (name.size() <= 58 - 2) { - cb.store_long(category, 16); + if (name.size() <= 58 - 32) { + cb.store_bytes(category.as_slice()); cb.store_long(0, 1); cb.store_long(name.size(), 6); cb.store_bytes(name); } else { - cb.store_long(category, 16); + cb.store_bytes(category.as_slice()); cb.store_long(1, 1); cb.store_ref(vm::CellBuilder().store_bytes(name).finalize()); } @@ -295,10 +303,9 @@ td::Result> ManualDns::create_set_all_unsigned(td::Spanprefetch_maybe_ref(dict_root); } - vm::Dictionary dict(dict_root, 16); + vm::Dictionary dict(dict_root, 256); if (!action.data.value().is_null()) { - auto key = dict.integer_key(td::make_refint(action.category), 16); - dict.set_ref(key.bits(), 16, action.data.value()); + dict.set_ref(action.category.bits(), 256, action.data.value()); } pdict.set(ptr, ptr_size, dict.get_root()); } @@ -340,14 +347,13 @@ td::Result> ManualDns::create_set_name_unsigned(td::Slice name cb.store_ref(vm::CellBuilder().store_bytes(name).finalize()); } - vm::Dictionary dict(16); + vm::Dictionary dict(256); for (auto& action : entries) { if (action.data.value().is_null()) { continue; } - auto key = dict.integer_key(td::make_refint(action.category), 16); - dict.set_ref(key.bits(), 16, action.data.value()); + dict.set_ref(action.category.cbits(), 256, action.data.value()); } cb.store_maybe_ref(dict.get_root_cell()); @@ -395,17 +401,16 @@ size_t ManualDns::get_max_name_size() const { return get_default_max_name_size(); } -td::Result> ManualDns::resolve_raw(td::Slice name, td::int32 category_big) const { - return TRY_VM(resolve_raw_or_throw(name, category_big)); +td::Result> ManualDns::resolve_raw(td::Slice name, td::Bits256 category) const { + return TRY_VM(resolve_raw_or_throw(name, category)); } td::Result> ManualDns::resolve_raw_or_throw(td::Slice name, - td::int32 category_big) const { - TRY_RESULT(category, td::narrow_cast_safe(category_big)); + td::Bits256 category) const { if (name.size() > get_max_name_size()) { return td::Status::Error("Name is too long"); } auto encoded_name = encode_name(name); - auto res = run_get_method(resolve_args_raw(encoded_name, category)); + auto res = run_get_method(resolve_args_raw(encoded_name, category, address_)); if (!res.success) { return td::Status::Error("get method failed"); } @@ -419,19 +424,22 @@ td::Result> ManualDns::resolve_raw_or_throw(td: return td::Status::Error("Prefix size is not divisible by 8"); } prefix_size /= 8; + if (prefix_size == 0) { + return vec; + } if (prefix_size < encoded_name.size()) { - vec.push_back({decode_name(td::Slice(encoded_name).substr(0, prefix_size)), -1, data}); + vec.push_back({decode_name(td::Slice(encoded_name).substr(0, prefix_size)), DNS_NEXT_RESOLVER_CATEGORY, + vm::load_cell_slice_ref(data), true}); } else { - if (category == 0) { - vm::Dictionary dict(std::move(data), 16); - dict.check_for_each([&](auto cs, auto x, auto y) { - td::BigInt256 cat; - cat.import_bits(x, y, true); - vec.push_back({name.str(), td::narrow_cast(cat.to_long()), cs->prefetch_ref()}); + if (category.is_zero()) { + vm::Dictionary dict(std::move(data), 256); + dict.check_for_each([&](auto cs, td::ConstBitPtr key, int n) { + CHECK(n == 256); + vec.push_back({name.str(), td::Bits256(key), cs}); return true; }); } else { - vec.push_back({name.str(), category, data}); + vec.push_back({name.str(), category, vm::load_cell_slice_ref(data)}); } } @@ -445,7 +453,7 @@ td::Result> ManualDns::create_update_query(CombinedActions> ManualDns::create_update_query(td::Ed25519::Privat std::string DnsInterface::encode_name(td::Slice name) { std::string res; + if (name.empty() || name == ".") { + res += '\0'; + return res; + } while (!name.empty()) { auto pos = name.rfind('.'); - if (pos == name.npos) { + if (pos == td::Slice::npos) { res += name.str(); name = td::Slice(); } else { @@ -504,20 +516,15 @@ std::string DnsInterface::encode_name(td::Slice name) { std::string DnsInterface::decode_name(td::Slice name) { std::string res; - if (!name.empty() && name.back() == 0) { - name.remove_suffix(1); - } while (!name.empty()) { auto pos = name.rfind('\0'); - if (!res.empty()) { - res += '.'; - } - if (pos == name.npos) { + if (pos == td::Slice::npos) { res += name.str(); name = td::Slice(); } else { res += name.substr(pos + 1).str(); name.truncate(pos); + res += '.'; } } return res; @@ -570,17 +577,16 @@ td::Result ManualDns::parse_line(td::Slice cmd) { if (type == "set") { auto name = parser.read_word(); auto category_str = parser.read_word(); - TRY_RESULT(category, td::to_integer_safe(category_str)); TRY_RESULT(data, parse_data(parser.read_all())); - return ManualDns::ActionExt{name.str(), category, std::move(data)}; + return ManualDns::ActionExt{name.str(), td::sha256_bits256(td::as_slice(category_str)), std::move(data)}; } else if (type == "delete.name") { auto name = parser.read_word(); if (name.empty()) { return td::Status::Error("name is empty"); } - return ManualDns::ActionExt{name.str(), 0, {}}; + return ManualDns::ActionExt{name.str(), td::Bits256::zero(), {}}; } else if (type == "delete.all") { - return ManualDns::ActionExt{"", 0, {}}; + return ManualDns::ActionExt{"", td::Bits256::zero(), {}}; } return td::Status::Error(PSLICE() << "Unknown command: " << type); } diff --git a/crypto/smc-envelope/ManualDns.h b/crypto/smc-envelope/ManualDns.h index fbf12e74..545c3279 100644 --- a/crypto/smc-envelope/ManualDns.h +++ b/crypto/smc-envelope/ManualDns.h @@ -26,10 +26,14 @@ #include "smc-envelope/SmartContract.h" #include "Ed25519.h" +#include "common/checksum.h" #include namespace ton { +const td::Bits256 DNS_NEXT_RESOLVER_CATEGORY = + td::sha256_bits256(td::Slice("dns_next_resolver", strlen("dns_next_resolver"))); + class DnsInterface { public: struct EntryDataText { @@ -90,8 +94,9 @@ class DnsInterface { struct Entry { std::string name; - td::int16 category; + td::Bits256 category; EntryData data; + bool partially_resolved = false; auto key() const { return std::tie(name, category); } @@ -102,47 +107,48 @@ class DnsInterface { return key() == other.key() && data == other.data; } friend td::StringBuilder& operator<<(td::StringBuilder& sb, const Entry& entry) { - sb << entry.name << ":" << entry.category << ":" << entry.data; + sb << entry.name << ":" << entry.category.to_hex() << ":" << entry.data; return sb; } }; struct RawEntry { std::string name; - td::int16 category; - td::Ref data; + td::Bits256 category; + td::Ref data; + bool partially_resolved = false; }; struct ActionExt { std::string name; - td::int16 category; + td::Bits256 category; td::optional data; static td::Result parse(td::Slice); }; struct Action { std::string name; - td::int16 category; + td::Bits256 category; td::optional> data; bool does_create_category() const { CHECK(!name.empty()); - CHECK(category != 0); + CHECK(!category.is_zero()); return static_cast(data); } bool does_change_empty() const { CHECK(!name.empty()); - CHECK(category != 0); + CHECK(!category.is_zero()); return static_cast(data) && data.value().not_null(); } void make_non_empty() { CHECK(!name.empty()); - CHECK(category != 0); + CHECK(!category.is_zero()); if (!data) { data = td::Ref(); } } friend td::StringBuilder& operator<<(td::StringBuilder& sb, const Action& action) { - sb << action.name << ":" << action.category << ":"; + sb << action.name << ":" << action.category.to_hex() << ":"; if (action.data) { if (action.data.value().is_null()) { sb << ""; @@ -156,15 +162,14 @@ class DnsInterface { } }; - virtual ~DnsInterface() { - } + virtual ~DnsInterface() = default; virtual size_t get_max_name_size() const = 0; - virtual td::Result> resolve_raw(td::Slice name, td::int32 category) const = 0; + virtual td::Result> resolve_raw(td::Slice name, td::Bits256 category) const = 0; virtual td::Result> create_update_query( td::Ed25519::PrivateKey& pk, td::Span actions, td::uint32 valid_until = std::numeric_limits::max()) const = 0; - td::Result> resolve(td::Slice name, td::int32 category) const; + td::Result> resolve(td::Slice name, td::Bits256 category) const; static std::string encode_name(td::Slice name); static std::string decode_name(td::Slice name); @@ -172,13 +177,16 @@ class DnsInterface { static size_t get_default_max_name_size() { return 128; } - static SmartContract::Args resolve_args_raw(td::Slice encoded_name, td::int16 category); - static td::Result resolve_args(td::Slice name, td::int32 category); + static SmartContract::Args resolve_args_raw(td::Slice encoded_name, td::Bits256 category, + block::StdAddress address = {}); + static td::Result resolve_args(td::Slice name, td::Bits256 category, + block::StdAddress address = {}); }; class ManualDns : public ton::SmartContract, public DnsInterface { public: - ManualDns(State state) : SmartContract(std::move(state)) { + ManualDns(State state, block::StdAddress address = {}) + : SmartContract(std::move(state)), address_(std::move(address)) { } ManualDns* make_copy() const override { @@ -186,8 +194,8 @@ class ManualDns : public ton::SmartContract, public DnsInterface { } // creation - static td::Ref create(State state) { - return td::Ref(true, std::move(state)); + static td::Ref create(State state, block::StdAddress address = {}) { + return td::Ref(true, std::move(state), std::move(address)); } static td::Ref create(td::Ref data = {}, int revision = 0); static td::Ref create(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id, int revision = 0); @@ -208,9 +216,9 @@ class ManualDns : public ton::SmartContract, public DnsInterface { td::Result get_wallet_id() const; td::Result get_wallet_id_or_throw() const; - td::Result> create_set_value_unsigned(td::int16 category, td::Slice name, + td::Result> create_set_value_unsigned(td::Bits256 category, td::Slice name, td::Ref data) const; - td::Result> create_delete_value_unsigned(td::int16 category, td::Slice name) const; + td::Result> create_delete_value_unsigned(td::Bits256 category, td::Slice name) const; td::Result> create_delete_all_unsigned() const; td::Result> create_set_all_unsigned(td::Span entries) const; td::Result> create_delete_name_unsigned(td::Slice name) const; @@ -222,8 +230,8 @@ class ManualDns : public ton::SmartContract, public DnsInterface { static td::Ref create_init_data_fast(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id); size_t get_max_name_size() const override; - td::Result> resolve_raw(td::Slice name, td::int32 category_big) const override; - td::Result> resolve_raw_or_throw(td::Slice name, td::int32 category_big) const; + td::Result> resolve_raw(td::Slice name, td::Bits256 category) const override; + td::Result> resolve_raw_or_throw(td::Slice name, td::Bits256 category) const; td::Result> create_init_query( const td::Ed25519::PrivateKey& private_key, @@ -235,10 +243,10 @@ class ManualDns : public ton::SmartContract, public DnsInterface { template struct CombinedActions { std::string name; - td::int16 category{0}; + td::Bits256 category = td::Bits256::zero(); td::optional> actions; friend td::StringBuilder& operator<<(td::StringBuilder& sb, const CombinedActions& action) { - sb << action.name << ":" << action.category << ":"; + sb << action.name << ":" << action.category.to_hex() << ":"; if (action.actions) { sb << "" << action.actions.value().size(); } else { @@ -251,7 +259,7 @@ class ManualDns : public ton::SmartContract, public DnsInterface { template static std::vector> combine_actions(td::Span actions) { struct Info { - std::set known_category; + std::set known_category; std::vector actions; bool closed{false}; bool non_empty{false}; @@ -278,7 +286,7 @@ class ManualDns : public ton::SmartContract, public DnsInterface { if (info.closed) { continue; } - if (action.category != 0 && action.does_create_category()) { + if (!action.category.is_zero() && action.does_create_category()) { info.non_empty = true; } if (!info.known_category.insert(action.category).second) { @@ -330,6 +338,8 @@ class ManualDns : public ton::SmartContract, public DnsInterface { return res; } td::Result> create_update_query(CombinedActions& combined) const; + private: + block::StdAddress address_; }; } // namespace ton diff --git a/crypto/test/modbigint.cpp b/crypto/test/modbigint.cpp index 851f0f9b..b6480d38 100644 --- a/crypto/test/modbigint.cpp +++ b/crypto/test/modbigint.cpp @@ -786,7 +786,9 @@ struct ModArray { } ModArray& operator/=(const ModArray& other) { - assert(try_divide(other) && "division by zero?"); + if (!try_divide(other)) { + assert(false); // division by zero? + } return *this; } @@ -1051,7 +1053,9 @@ void init_invm() { for (int i = 0; i < mod_cnt; i++) { assert(mod[i] > 0 && mod[i] <= (1 << 30)); for (int j = 0; j < i; j++) { - assert(gcdx(mod[i], mod[j], invm[i][j], invm[j][i]) == 1); + if (gcdx(mod[i], mod[j], invm[i][j], invm[j][i]) != 1) { + assert(false); + } if (invm[i][j] < 0) { invm[i][j] += mod[j]; } diff --git a/crypto/test/test-smartcont.cpp b/crypto/test/test-smartcont.cpp index 370a36e8..673bb758 100644 --- a/crypto/test/test-smartcont.cpp +++ b/crypto/test/test-smartcont.cpp @@ -810,7 +810,7 @@ class MapDns { using ManualDns = ton::ManualDns; struct Entry { std::string name; - td::int16 category{0}; + td::Bits256 category = td::Bits256::zero(); std::string text; auto key() const { @@ -827,34 +827,34 @@ class MapDns { return key() == other.key() && text == other.text; } friend td::StringBuilder& operator<<(td::StringBuilder& sb, const Entry& entry) { - return sb << "[" << entry.name << ":" << entry.category << ":" << entry.text << "]"; + return sb << "[" << entry.name << ":" << entry.category.to_hex() << ":" << entry.text << "]"; } }; struct Action { std::string name; - td::int16 category{0}; + td::Bits256 category = td::Bits256::zero(); td::optional text; bool does_create_category() const { CHECK(!name.empty()); - CHECK(category != 0); + CHECK(!category.is_zero()); return static_cast(text); } bool does_change_empty() const { CHECK(!name.empty()); - CHECK(category != 0); + CHECK(!category.is_zero()); return static_cast(text) && !text.value().empty(); } void make_non_empty() { CHECK(!name.empty()); - CHECK(category != 0); + CHECK(!category.is_zero()); if (!text) { text = ""; } } friend td::StringBuilder& operator<<(td::StringBuilder& sb, const Action& entry) { - return sb << "[" << entry.name << ":" << entry.category << ":" << (entry.text ? entry.text.value() : "") - << "]"; + return sb << "[" << entry.name << ":" << entry.category.to_hex() << ":" + << (entry.text ? entry.text.value() : "") << "]"; } }; void update(td::Span actions) { @@ -868,7 +868,7 @@ class MapDns { LOG(ERROR) << td::format::as_array(actions); auto combined_actions = ton::ManualDns::combine_actions(actions); for (auto& c : combined_actions) { - LOG(ERROR) << c.name << ":" << c.category; + LOG(ERROR) << c.name << ":" << c.category.to_hex(); if (c.actions) { LOG(ERROR) << td::format::as_array(c.actions.value()); } @@ -879,7 +879,7 @@ class MapDns { } } - std::vector resolve(td::Slice name, td::int16 category) { + std::vector resolve(td::Slice name, td::Bits256 category) { std::vector res; if (name.empty()) { for (auto& a : entries_) { @@ -891,7 +891,7 @@ class MapDns { auto it = entries_.find(name); while (it == entries_.end()) { auto sz = name.find('.'); - category = -1; + category = ton::DNS_NEXT_RESOLVER_CATEGORY; if (sz != td::Slice::npos) { name = name.substr(sz + 1); } else { @@ -901,7 +901,7 @@ class MapDns { } if (it != entries_.end()) { for (auto& b : it->second) { - if (category == 0 || category == b.first) { + if (category.is_zero() || category == b.first) { res.push_back({name.str(), b.first, b.second}); } } @@ -913,13 +913,13 @@ class MapDns { } private: - std::map, std::less<>> entries_; + std::map, std::less<>> entries_; void do_update(const Action& action) { if (action.name.empty()) { entries_.clear(); return; } - if (action.category == 0) { + if (action.category.is_zero()) { entries_.erase(action.name); return; } @@ -946,7 +946,7 @@ class MapDns { } for (auto& action : actions.actions.value()) { CHECK(!action.name.empty()); - CHECK(action.category != 0); + CHECK(!action.category.is_zero()); CHECK(action.text); if (action.text.value().empty()) { entries_[action.name]; @@ -956,7 +956,7 @@ class MapDns { } return; } - if (actions.category == 0) { + if (!actions.category.is_zero()) { entries_.erase(actions.name); LOG(ERROR) << "CLEAR " << actions.name; if (!actions.actions) { @@ -965,7 +965,7 @@ class MapDns { entries_[actions.name]; for (auto& action : actions.actions.value()) { CHECK(action.name == actions.name); - CHECK(action.category != 0); + CHECK(!action.category.is_zero()); CHECK(action.text); if (action.text.value().empty()) { entries_[action.name]; @@ -979,7 +979,7 @@ class MapDns { CHECK(actions.actions.value().size() == 1); for (auto& action : actions.actions.value()) { CHECK(action.name == actions.name); - CHECK(action.category != 0); + CHECK(!action.category.is_zero()); if (action.text) { if (action.text.value().empty()) { entries_[action.name].erase(action.category); @@ -1036,8 +1036,8 @@ class CheckedDns { return update(td::span_one(action)); } - std::vector resolve(td::Slice name, td::int16 category) { - LOG(ERROR) << "RESOLVE: " << name << " " << category; + std::vector resolve(td::Slice name, td::Bits256 category) { + LOG(ERROR) << "RESOLVE: " << name << " " << category.to_hex(); auto res = map_dns_.resolve(name, category); LOG(ERROR) << td::format::as_array(res); @@ -1092,6 +1092,12 @@ class CheckedDns { } }; +static td::Bits256 intToCat(int x) { + td::Bits256 cat = td::Bits256::zero(); + cat.as_slice().copy_from(td::Slice((char*)&x, sizeof(x))); + return cat; +} + void do_dns_test(CheckedDns&& dns) { using Action = CheckedDns::Action; std::vector actions; @@ -1130,7 +1136,7 @@ void do_dns_test(CheckedDns&& dns) { if (rnd.fast(0, 20) == 0) { return action; } - action.category = td::narrow_cast(rnd.fast(1, 5)); + action.category = intToCat(rnd.fast(1, 5)); if (rnd.fast(0, 4) == 0) { return action; } @@ -1150,7 +1156,8 @@ void do_dns_test(CheckedDns&& dns) { actions.clear(); } auto name = gen_name(); - dns.resolve(name, td::narrow_cast(rnd.fast(0, 5))); + auto category = td::Bits256::zero(); + dns.resolve(name, intToCat(rnd.fast(0, 5))); } }; @@ -1167,7 +1174,7 @@ TEST(Smartcont, DnsManual) { CHECK(td::Slice("a\0b\0") == ManualDns::encode_name("b.a")); CHECK(td::Slice("a\0b\0") == ManualDns::encode_name(".b.a")); - ASSERT_EQ("b.a", ManualDns::decode_name("a\0b\0")); + ASSERT_EQ(".b.a", ManualDns::decode_name("a\0b\0")); ASSERT_EQ("b.a", ManualDns::decode_name("a\0b")); ASSERT_EQ("", ManualDns::decode_name("")); @@ -1184,8 +1191,8 @@ TEST(Smartcont, DnsManual) { auto value = vm::CellBuilder().store_bytes("hello world").finalize(); auto set_query = manual - ->sign(key, - manual->prepare(manual->create_set_value_unsigned(1, "a\0b\0", value).move_as_ok(), 1).move_as_ok()) + ->sign(key, manual->prepare(manual->create_set_value_unsigned(intToCat(1), "a\0b\0", value).move_as_ok(), 1) + .move_as_ok()) .move_as_ok(); CHECK(manual.write().send_external_message(set_query).code == 0); @@ -1195,46 +1202,48 @@ TEST(Smartcont, DnsManual) { CHECK(res.stack.write().pop_cell()->get_hash() == value->get_hash()); CheckedDns dns; - dns.update(CheckedDns::Action{"a.b.c", 1, "hello"}); - CHECK(dns.resolve("a.b.c", 1).at(0).text == "hello"); - dns.resolve("a", 1); - dns.resolve("a.b", 1); - CHECK(dns.resolve("a.b.c", 2).empty()); - dns.update(CheckedDns::Action{"a.b.c", 2, "test"}); - CHECK(dns.resolve("a.b.c", 2).at(0).text == "test"); - dns.resolve("a.b.c", 1); - dns.resolve("a.b.c", 2); + dns.update(CheckedDns::Action{"a.b.c", intToCat(1), "hello"}); + CHECK(dns.resolve("a.b.c", intToCat(1)).at(0).text == "hello"); + dns.resolve("a", intToCat(1)); + dns.resolve("a.b", intToCat(1)); + CHECK(dns.resolve("a.b.c", intToCat(2)).empty()); + dns.update(CheckedDns::Action{"a.b.c", intToCat(2), "test"}); + CHECK(dns.resolve("a.b.c", intToCat(2)).at(0).text == "test"); + dns.resolve("a.b.c", intToCat(1)); + dns.resolve("a.b.c", intToCat(2)); LOG(ERROR) << "Test zero category"; - dns.resolve("a.b.c", 0); - dns.update(CheckedDns::Action{"", 0, ""}); - CHECK(dns.resolve("a.b.c", 2).empty()); + dns.resolve("a.b.c", intToCat(0)); + dns.update(CheckedDns::Action{"", intToCat(0), ""}); + CHECK(dns.resolve("a.b.c", intToCat(2)).empty()); LOG(ERROR) << "Test multipe update"; { - CheckedDns::Action e[4] = {CheckedDns::Action{"", 0, ""}, CheckedDns::Action{"a.b.c", 1, "hello"}, - CheckedDns::Action{"a.b.c", 2, "world"}, CheckedDns::Action{"x.y.z", 3, "abc"}}; + CheckedDns::Action e[4] = { + CheckedDns::Action{"", intToCat(0), ""}, CheckedDns::Action{"a.b.c", intToCat(1), "hello"}, + CheckedDns::Action{"a.b.c", intToCat(2), "world"}, CheckedDns::Action{"x.y.z", intToCat(3), "abc"}}; dns.update(td::span(e, 4)); } - dns.resolve("a.b.c", 1); - dns.resolve("a.b.c", 2); - dns.resolve("x.y.z", 3); + dns.resolve("a.b.c", intToCat(1)); + dns.resolve("a.b.c", intToCat(2)); + dns.resolve("x.y.z", intToCat(3)); - dns.update(td::span_one(CheckedDns::Action{"x.y.z", 0, ""})); + dns.update(td::span_one(CheckedDns::Action{"x.y.z", intToCat(0), ""})); - dns.resolve("a.b.c", 1); - dns.resolve("a.b.c", 2); - dns.resolve("x.y.z", 3); + dns.resolve("a.b.c", intToCat(1)); + dns.resolve("a.b.c", intToCat(2)); + dns.resolve("x.y.z", intToCat(3)); { - CheckedDns::Action e[3] = {CheckedDns::Action{"x.y.z", 0, ""}, CheckedDns::Action{"x.y.z", 1, "xxx"}, - CheckedDns::Action{"x.y.z", 2, "yyy"}}; + CheckedDns::Action e[3] = {CheckedDns::Action{"x.y.z", intToCat(0), ""}, + CheckedDns::Action{"x.y.z", intToCat(1), "xxx"}, + CheckedDns::Action{"x.y.z", intToCat(2), "yyy"}}; dns.update(td::span(e, 3)); } - dns.resolve("a.b.c", 1); - dns.resolve("a.b.c", 2); - dns.resolve("x.y.z", 1); - dns.resolve("x.y.z", 2); - dns.resolve("x.y.z", 3); + dns.resolve("a.b.c", intToCat(1)); + dns.resolve("a.b.c", intToCat(2)); + dns.resolve("x.y.z", intToCat(1)); + dns.resolve("x.y.z", intToCat(2)); + dns.resolve("x.y.z", intToCat(3)); { auto actions_ext = @@ -1250,8 +1259,8 @@ TEST(Smartcont, DnsManual) { dns.update(actions); } - dns.resolve("one", 1); - dns.resolve("two", 2); + dns.resolve("one", intToCat(1)); + dns.resolve("two", intToCat(2)); // TODO: rethink semantic of creating an empty dictionary do_dns_test(CheckedDns(true, true)); diff --git a/crypto/vm/stack.hpp b/crypto/vm/stack.hpp index 32040bd7..2de7c1e4 100644 --- a/crypto/vm/stack.hpp +++ b/crypto/vm/stack.hpp @@ -320,7 +320,7 @@ class Stack : public td::CntObject { Stack(const Stack& old_stack, unsigned copy_elem, unsigned skip_top); Stack(Stack&& old_stack, unsigned copy_elem, unsigned skip_top); td::CntObject* make_copy() const override { - std::cerr << "copy stack at " << (const void*)this << " (" << depth() << " entries)\n"; + //std::cerr << "copy stack at " << (const void*)this << " (" << depth() << " entries)\n"; return new Stack{stack}; } void push_from_stack(const Stack& old_stack, unsigned copy_elem, unsigned skip_top = 0); diff --git a/lite-client/lite-client.cpp b/lite-client/lite-client.cpp index f472af21..aad3ae6e 100644 --- a/lite-client/lite-client.cpp +++ b/lite-client/lite-client.cpp @@ -62,6 +62,7 @@ #include "openssl/rand.hpp" #include "crypto/vm/utils.h" #include "crypto/common/util.h" +#include "common/checksum.h" #if TD_DARWIN || TD_LINUX #include @@ -1025,11 +1026,13 @@ bool TestNode::do_parse_line() { workchain = ton::workchainInvalid; bool step = (word.size() > 10); std::string domain; - int cat = 0; + std::string cat_str; return (!step || parse_account_addr(workchain, addr)) && get_word_to(domain) && (parse_block_id_ext(domain, blkid) ? get_word_to(domain) : (blkid = mc_last_id_).is_valid()) && - (seekeoln() || parse_int16(cat)) && seekeoln() && - dns_resolve_start(workchain, addr, blkid, domain, cat, step); + (seekeoln() || get_word_to(cat_str)) && seekeoln() && + dns_resolve_start(workchain, addr, blkid, domain, + cat_str.empty() ? td::Bits256::zero() : td::sha256_bits256(td::as_slice(cat_str)), + step ? 3 : 0); } else if (word == "allshards" || word == "allshardssave") { std::string filename; return (word.size() <= 9 || get_word_to(filename)) && @@ -1599,37 +1602,42 @@ void TestNode::send_compute_complaint_price_query(ton::StdSmcAddress elector_add } bool TestNode::dns_resolve_start(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt blkid, - std::string domain, int cat, int mode) { - if (domain.size() > 1023) { - return set_error("domain name too long"); - } + std::string domain, td::Bits256 cat, int mode) { if (domain.size() >= 2 && domain[0] == '"' && domain.back() == '"') { domain.erase(0, 1); domain.pop_back(); } std::vector components; - std::size_t i, p = 0; - for (i = 0; i < domain.size(); i++) { - if (!domain[i] || (unsigned char)domain[i] >= 0xfe || (unsigned char)domain[i] <= ' ') { - return set_error("invalid characters in a domain name"); - } - if (domain[i] == '.') { - if (i == p) { - return set_error("domain name cannot have an empty component"); + if (domain != ".") { + std::size_t i, p = 0; + for (i = 0; i < domain.size(); i++) { + if (!domain[i] || (unsigned char)domain[i] >= 0xfe || (unsigned char)domain[i] <= ' ') { + return set_error("invalid characters in a domain name"); } + if (domain[i] == '.') { + if (i == p) { + return set_error("domain name cannot have an empty component"); + } + components.emplace_back(domain, p, i - p); + p = i + 1; + } + } + if (i > p) { components.emplace_back(domain, p, i - p); - p = i + 1; } } - if (i > p) { - components.emplace_back(domain, p, i - p); + std::string qdomain; + if (mode & 2) { + qdomain += '\0'; } - std::string qdomain, qdomain0; while (!components.empty()) { qdomain += components.back(); qdomain += '\0'; components.pop_back(); } + if (qdomain.size() > 127) { + return set_error("domain name too long"); + } if (!(ready_ && !client_.empty())) { return set_error("server connection not ready"); @@ -1657,26 +1665,18 @@ bool TestNode::dns_resolve_start(ton::WorkchainId workchain, ton::StdSmcAddress } bool TestNode::dns_resolve_send(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt blkid, - std::string domain, std::string qdomain, int cat, int mode) { + std::string domain, std::string qdomain, td::Bits256 cat, int mode) { LOG(INFO) << "dns_resolve for '" << domain << "' category=" << cat << " mode=" << mode << " starting from smart contract " << workchain << ":" << addr.to_hex() << " with respect to block " << blkid.to_str(); - std::string qdomain0; - if (qdomain.size() <= 127) { - qdomain0 = qdomain; - } else { - qdomain0 = std::string{qdomain, 0, 127}; - qdomain[125] = '\xff'; - qdomain[126] = '\x0'; - } vm::CellBuilder cb; Ref cell; - if (!(cb.store_bytes_bool(td::Slice(qdomain0)) && cb.finalize_to(cell))) { + if (!(cb.store_bytes_bool(td::Slice(qdomain)) && cb.finalize_to(cell))) { return set_error("cannot store domain name into slice"); } std::vector params; - params.emplace_back(vm::load_cell_slice_ref(std::move(cell))); - params.emplace_back(td::make_refint(cat)); + params.emplace_back(vm::load_cell_slice_ref(cell)); + params.emplace_back(td::bits_to_refint(cat.cbits(), 256, false)); auto P = td::PromiseCreator::lambda([this, workchain, addr, blkid, domain, qdomain, cat, mode](td::Result> R) { if (R.is_error()) { @@ -1701,12 +1701,12 @@ bool TestNode::dns_resolve_send(ton::WorkchainId workchain, ton::StdSmcAddress a return start_run_method(workchain, addr, blkid, "dnsresolve", std::move(params), 0x1f, std::move(P)); } -bool TestNode::show_dns_record(std::ostream& os, int cat, Ref value, bool raw_dump) { +bool TestNode::show_dns_record(std::ostream& os, td::Bits256 cat, Ref value, bool raw_dump) { if (raw_dump) { bool ok = show_dns_record(os, cat, value, false); if (!ok) { os << "cannot parse dns record; raw value: "; - vm::load_cell_slice(value).print_rec(print_limit_, os); + value->print_rec(print_limit_, os); } return ok; } @@ -1715,11 +1715,11 @@ bool TestNode::show_dns_record(std::ostream& os, int cat, Ref value, b return true; } // block::gen::t_DNSRecord.print_ref(print_limit_, os, value); - if (!block::gen::t_DNSRecord.validate_ref(value)) { + if (!block::gen::t_DNSRecord.validate_csr(value)) { return false; } - block::gen::t_DNSRecord.print_ref(print_limit_, os, value); - auto cs = vm::load_cell_slice(value); + block::gen::t_DNSRecord.print(os, value, 0, print_limit_); + auto cs = *value; auto tag = block::gen::t_DNSRecord.get_tag(cs); ton::WorkchainId wc; ton::StdSmcAddress addr; @@ -1751,7 +1751,7 @@ bool TestNode::show_dns_record(std::ostream& os, int cat, Ref value, b } void TestNode::dns_resolve_finish(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt blkid, - std::string domain, std::string qdomain, int cat, int mode, int used_bits, + std::string domain, std::string qdomain, td::Bits256 cat, int mode, int used_bits, Ref value) { if (used_bits <= 0) { td::TerminalIO::out() << "domain '" << domain << "' not found" << std::endl; @@ -1761,12 +1761,12 @@ void TestNode::dns_resolve_finish(ton::WorkchainId workchain, ton::StdSmcAddress LOG(ERROR) << "too many bits used (" << used_bits << " out of " << qdomain.size() * 8 << ")"; return; } - int pos = (used_bits >> 3); - if (qdomain[pos - 1]) { + size_t pos = used_bits >> 3; + bool end = pos == qdomain.size(); + if (!end && qdomain[pos - 1] && qdomain[pos]) { LOG(ERROR) << "domain split not at a component boundary"; return; } - bool end = ((std::size_t)pos == qdomain.size()); if (!end) { LOG(INFO) << "partial information obtained"; if (value.is_null()) { @@ -1778,7 +1778,7 @@ void TestNode::dns_resolve_finish(ton::WorkchainId workchain, ton::StdSmcAddress ton::StdSmcAddress nx_addr; if (!(block::gen::t_DNSRecord.cell_unpack_dns_next_resolver(value, nx_address) && block::tlb::t_MsgAddressInt.extract_std_address(std::move(nx_address), nx_wc, nx_addr))) { - LOG(ERROR) << "cannot parse next resolver info for " << domain.substr(qdomain.size() - pos); + LOG(ERROR) << "cannot parse next resolver info for " << domain.substr(qdomain.size() - pos - 1); std::ostringstream out; vm::load_cell_slice(value).print_rec(print_limit_, out); td::TerminalIO::err() << out.str() << std::endl; @@ -1792,37 +1792,41 @@ void TestNode::dns_resolve_finish(ton::WorkchainId workchain, ton::StdSmcAddress LOG(ERROR) << "cannot send next dns query"; return; } - LOG(INFO) << "recursive dns query to '" << domain.substr(qdomain.size() - pos) << "' sent"; + LOG(INFO) << "recursive dns query to '" << domain.substr(qdomain.size() - pos - 1) << "' sent"; return; } auto out = td::TerminalIO::out(); - out << "Result for domain '" << domain << "' category " << cat << (cat ? "" : " (all categories)") << std::endl; + if (cat.is_zero()) { + out << "Result for domain '" << domain << "' (all categories)" << std::endl; + } else { + out << "Result for domain '" << domain << "' category " << cat << std::endl; + } try { if (value.not_null()) { std::ostringstream os0; vm::load_cell_slice(value).print_rec(print_limit_, os0); out << "raw data: " << os0.str() << std::endl; } - if (!cat) { - vm::Dictionary dict{value, 16}; + if (cat.is_zero()) { + vm::Dictionary dict{value, 256}; if (!dict.check_for_each([this, &out](Ref cs, td::ConstBitPtr key, int n) { - CHECK(n == 16); - int x = (int)key.get_int(16); - if (cs.is_null() || cs->size_ext() != 0x10000) { - out << "category #" << x << " : value is not a reference" << std::endl; - return false; - } + CHECK(n == 256); + td::Bits256 x{key}; + /*if (cs.is_null() || cs->size_ext() != 0x10000) { + out << "category " << x << " : value is not a reference" << std::endl; + return true; + }*/ std::ostringstream os; - (void)show_dns_record(os, x, cs->prefetch_ref(), true); - out << "category #" << x << " : " << os.str() << std::endl; + (void)show_dns_record(os, x, cs, true); + out << "category " << x << " : " << os.str() << std::endl; return true; })) { out << "invalid dns record dictionary" << std::endl; } } else { std::ostringstream os; - (void)show_dns_record(os, cat, value, true); - out << "category #" << cat << " : " << os.str() << std::endl; + (void)show_dns_record(os, cat, value.is_null() ? Ref() : vm::load_cell_slice_ref(value), true); + out << "category " << cat << " : " << os.str() << std::endl; } } catch (vm::VmError& err) { LOG(ERROR) << "vm error while traversing dns resolve result: " << err.get_msg(); diff --git a/lite-client/lite-client.h b/lite-client/lite-client.h index 00d8bd07..e62e801c 100644 --- a/lite-client/lite-client.h +++ b/lite-client/lite-client.h @@ -213,13 +213,13 @@ class TestNode : public td::actor::Actor { bool register_config_param1(Ref value); bool register_config_param4(Ref value); bool dns_resolve_start(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt blkid, std::string domain, - int cat, int mode); + td::Bits256 cat, int mode); bool dns_resolve_send(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt blkid, std::string domain, - std::string qdomain, int cat, int mode); + std::string qdomain, td::Bits256 cat, int mode); void dns_resolve_finish(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt blkid, - std::string domain, std::string qdomain, int cat, int mode, int used_bits, + std::string domain, std::string qdomain, td::Bits256 cat, int mode, int used_bits, Ref value); - bool show_dns_record(std::ostream& os, int cat, Ref value, bool raw_dump); + bool show_dns_record(std::ostream& os, td::Bits256 cat, Ref value, bool raw_dump); bool get_all_shards(std::string filename = "", bool use_last = true, ton::BlockIdExt blkid = {}); void got_all_shards(ton::BlockIdExt blk, td::BufferSlice proof, td::BufferSlice data, std::string filename); bool parse_get_config_params(ton::BlockIdExt blkid, int mode = 0, std::string filename = "", diff --git a/rldp-http-proxy/rldp-http-proxy.cpp b/rldp-http-proxy/rldp-http-proxy.cpp index 59533c50..fb5ae4c1 100644 --- a/rldp-http-proxy/rldp-http-proxy.cpp +++ b/rldp-http-proxy/rldp-http-proxy.cpp @@ -1073,7 +1073,8 @@ void TcpToRldpRequestSender::resolve() { ton::dht::DhtKey dht_key{key.compute_short_id(), "http." + host_, 0}; td::actor::send_closure(dht_, &ton::dht::Dht::get_value, std::move(dht_key), std::move(P)); } else { - auto obj = tonlib_api::make_object(nullptr, host_, 0, 16); + td::Bits256 category = td::sha256_bits256(td::Slice("site", 4)); + auto obj = tonlib_api::make_object(nullptr, host_, category, 16); auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result> R) { diff --git a/tl/generate/generate_common.cpp b/tl/generate/generate_common.cpp index c824f0f4..0068ccbd 100644 --- a/tl/generate/generate_common.cpp +++ b/tl/generate/generate_common.cpp @@ -74,11 +74,11 @@ int main() { generate_cpp( "auto/tl", "tonlib_api", "std::string", "std::string", "td::SecureString", "td::SecureString", {"\"tl/tl_jni_object.h\"", "\"tl/tl_object_store.h\"", "\"td/utils/int_types.h\""}, - {"", "\"td/utils/SharedSlice.h\""}); + {"", "\"td/utils/SharedSlice.h\"", "\"crypto/common/bitstring.h\""}); #else generate_cpp<>("auto/tl", "tonlib_api", "std::string", "std::string", "td::SecureString", "td::SecureString", {"\"tl/tl_object_parse.h\"", "\"tl/tl_object_store.h\"", "\"td/utils/int_types.h\""}, - {"", "\"td/utils/SharedSlice.h\""}); + {"", "\"td/utils/SharedSlice.h\"", "\"crypto/common/bitstring.h\""}); #endif td::gen_json_converter(td::tl::read_tl_config_from_file("scheme/tonlib_api.tlo"), "auto/tl/tonlib_api_json", "tonlib_api", td::tl::TL_writer::Mode::All); diff --git a/tl/generate/scheme/tonlib_api.tl b/tl/generate/scheme/tonlib_api.tl index d5f97cce..c1c3966f 100644 --- a/tl/generate/scheme/tonlib_api.tl +++ b/tl/generate/scheme/tonlib_api.tl @@ -4,6 +4,7 @@ string ? = String; int32 = Int32; int53 = Int53; int64 = Int64; +int256 8*[ int32 ] = Int256; bytes = Bytes; secureString = SecureString; secureBytes = SecureBytes; @@ -54,6 +55,8 @@ raw.message source:accountAddress destination:accountAddress value:int64 fwd_fee raw.transaction utime:int53 data:bytes transaction_id:internal.transactionId fee:int64 storage_fee:int64 other_fee:int64 in_msg:raw.message out_msgs:vector = raw.Transaction; raw.transactions transactions:vector previous_transaction_id:internal.transactionId = raw.Transactions; +raw.extMessageInfo body_hash:bytes = raw.ExtMessageInfo; + pchan.config alice_public_key:string alice_address:accountAddress bob_public_key:string bob_address:accountAddress init_timeout:int32 close_timeout:int32 channel_id:int64 = pchan.Config; raw.initialAccountState code:bytes data:bytes = InitialAccountState; @@ -117,11 +120,11 @@ dns.entryDataNextResolver resolver:AccountAddress = dns.EntryData; dns.entryDataSmcAddress smc_address:AccountAddress = dns.EntryData; dns.entryDataAdnlAddress adnl_address:AdnlAddress = dns.EntryData; -dns.entry name:string category:int32 entry:dns.EntryData = dns.Entry; +dns.entry name:string category:int256 entry:dns.EntryData = dns.Entry; dns.actionDeleteAll = dns.Action; // use category = 0 to delete all entries -dns.actionDelete name:string category:int32 = dns.Action; +dns.actionDelete name:string category:int256 = dns.Action; dns.actionSet entry:dns.entry = dns.Action; dns.resolved entries:vector = dns.Resolved; @@ -245,7 +248,7 @@ getBip39Hints prefix:string = Bip39Hints; //raw.init initial_account_state:raw.initialAccountState = Ok; raw.getAccountState account_address:accountAddress = raw.FullAccountState; raw.getTransactions private_key:InputKey account_address:accountAddress from_transaction_id:internal.transactionId = raw.Transactions; -raw.sendMessage body:bytes = Ok; +raw.sendMessage body:bytes = raw.ExtMessageInfo; raw.createAndSendMessage destination:accountAddress initial_account_state:bytes data:bytes = Ok; raw.createQuery destination:accountAddress init_code:bytes init_data:bytes body:bytes = query.Info; @@ -283,7 +286,7 @@ smc.getData id:int53 = tvm.Cell; smc.getState id:int53 = tvm.Cell; smc.runGetMethod id:int53 method:smc.MethodId stack:vector = smc.RunResult; -dns.resolve account_address:accountAddress name:string category:int32 ttl:int32 = dns.Resolved; +dns.resolve account_address:accountAddress name:string category:int256 ttl:int32 = dns.Resolved; pchan.signPromise input_key:InputKey promise:pchan.promise = pchan.Promise; pchan.validatePromise public_key:bytes promise:pchan.promise = Ok; diff --git a/tl/generate/scheme/tonlib_api.tlo b/tl/generate/scheme/tonlib_api.tlo index 05c56ac0..0bf3f39e 100644 Binary files a/tl/generate/scheme/tonlib_api.tlo and b/tl/generate/scheme/tonlib_api.tlo differ diff --git a/tonlib/test/offline.cpp b/tonlib/test/offline.cpp index 634aacf3..a1e5a0f6 100644 --- a/tonlib/test/offline.cpp +++ b/tonlib/test/offline.cpp @@ -575,83 +575,92 @@ TEST(Tonlib, ConfigCache) { nullptr, make_object("testdir")))) .ensure(); + auto mainnet = R"abc({ + "liteservers": [ + ], + "validator": { + "@type": "validator.config.global", + "zero_state": { + "workchain": -1, + "shard": -9223372036854775808, + "seqno": 0, + "root_hash": "F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=", + "file_hash": "XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24=" + }, + "hardforks": [ + { + "file_hash": "t/9VBPODF7Zdh4nsnA49dprO69nQNMqYL+zk5bCjV/8=", + "seqno": 8536841, + "root_hash": "08Kpc9XxrMKC6BF/FeNHPS3MEL1/Vi/fQU/C9ELUrkc=", + "workchain": -1, + "shard": -9223372036854775808 + } + ] + } + })abc"; auto testnet = R"abc({ - "liteservers": [ - ], - "validator": { - "@type": "validator.config.global", - "zero_state": { - "workchain": -1, - "shard": -9223372036854775808, - "seqno": 0, - "root_hash": "VCSXxDHhTALFxReyTZRd8E4Ya3ySOmpOWAS4rBX9XBY=", - "file_hash": "eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo=" + "liteservers": [ + ], + "validator": { + "@type": "validator.config.global", + "zero_state": { + "workchain": -1, + "shard": -9223372036854775808, + "seqno": 0, + "root_hash": "gj+B8wb/AmlPk1z1AhVI484rhrUpgSr2oSFIh56VoSg=", + "file_hash": "Z+IKwYS54DmmJmesw/nAD5DzWadnOCMzee+kdgSYDOg=" + } } - } -})abc"; - auto testnet2 = R"abc({ - "liteservers": [ - ], - "validator": { - "@type": "validator.config.global", - "zero_state": { - "workchain": -1, - "shard": -9223372036854775808, - "seqno": 0, - "root_hash": "F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=", - "file_hash": "XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24=" + })abc"; + auto custom = R"abc({ + "liteservers": [ + ], + "validator": { + "@type": "validator.config.global", + "zero_state": { + "workchain": -1, + "shard": -9223372036854775808, + "seqno": 0, + "root_hash": "ZXSXxDHhTALFxReyTZRd8E4Ya3ySOmpOWAS4rBX9XBY=", + "file_hash": "eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo=" + } } - } -})abc"; - auto testnet3 = R"abc({ - "liteservers": [ - ], - "validator": { - "@type": "validator.config.global", - "zero_state": { - "workchain": -1, - "shard": -9223372036854775808, - "seqno": 0, - "root_hash": "ZXSXxDHhTALFxReyTZRd8E4Ya3ySOmpOWAS4rBX9XBY=", - "file_hash": "eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo=" - } - } -})abc"; + })abc"; auto bad = R"abc({ - "liteservers": [ - ], - "validator": { - "@type": "validator.config.global", - "zero_state": { - "workchain": -1, - "shard": -9223372036854775808, - "seqno": 0, - "file_hash": "eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo=" + "liteservers": [ + ], + "validator": { + "@type": "validator.config.global", + "zero_state": { + "workchain": -1, + "shard": -9223372036854775808, + "seqno": 0, + "file_hash": "eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo=" + } } - } -})abc"; + })abc"; sync_send(client, make_object(make_object(bad, "", true, false))) .ensure_error(); + sync_send(client, + make_object(make_object(mainnet, "", true, false))) + .ensure(); sync_send(client, make_object(make_object(testnet, "", true, false))) .ensure(); sync_send(client, - make_object(make_object(testnet2, "", true, false))) - .ensure(); - sync_send(client, - make_object(make_object(testnet3, "", true, false))) + make_object(make_object(custom, "", true, false))) .ensure(); sync_send(client, make_object( - make_object(testnet2, "testnet", true, false))) + make_object(mainnet, "testnet", true, false))) .ensure_error(); sync_send(client, make_object( - make_object(testnet2, "testnet2", true, false))) + make_object(testnet, "testnet", true, false))) .ensure(); sync_send(client, make_object( - make_object(testnet3, "testnet2", true, false))) + make_object(custom, "testnet", true, false))) .ensure_error(); } diff --git a/tonlib/test/online.cpp b/tonlib/test/online.cpp index 3b6a554c..52f51720 100644 --- a/tonlib/test/online.cpp +++ b/tonlib/test/online.cpp @@ -594,7 +594,8 @@ void dns_resolve(Client& client, const Wallet& dns, std::string name) { using namespace ton::tonlib_api; auto address = dns.get_address(); auto resolved = - sync_send(client, make_object<::ton::tonlib_api::dns_resolve>(std::move(address), name, 1, 4)).move_as_ok(); + sync_send(client, make_object<::ton::tonlib_api::dns_resolve>( + std::move(address), name, td::sha256_bits256(td::Slice("cat", 3)), 4)).move_as_ok(); CHECK(resolved->entries_.size() == 1); LOG(INFO) << to_string(resolved); LOG(INFO) << "OK"; @@ -747,13 +748,16 @@ void test_dns(Client& client, const Wallet& giver_wallet) { std::vector> actions; actions.push_back(make_object( - make_object("A", -1, make_object(A_B.get_address())))); + make_object("A", ton::DNS_NEXT_RESOLVER_CATEGORY, + make_object(A_B.get_address())))); auto init_A = create_update_dns_query(client, A, std::move(actions)).move_as_ok(); actions.push_back(make_object( - make_object("B", -1, make_object(A_B_C.get_address())))); + make_object("B", ton::DNS_NEXT_RESOLVER_CATEGORY, + make_object(A_B_C.get_address())))); auto init_A_B = create_update_dns_query(client, A_B, std::move(actions)).move_as_ok(); actions.push_back( - make_object(make_object("C", 1, make_object("Hello dns")))); + make_object(make_object("C", td::sha256_bits256(td::Slice("cat", 3)), + make_object("Hello dns")))); auto init_A_B_C = create_update_dns_query(client, A_B_C, std::move(actions)).move_as_ok(); LOG(INFO) << "Send dns init queries"; diff --git a/tonlib/tonlib/TonlibClient.cpp b/tonlib/tonlib/TonlibClient.cpp index 2696bb1a..6e55108d 100644 --- a/tonlib/tonlib/TonlibClient.cpp +++ b/tonlib/tonlib/TonlibClient.cpp @@ -1939,103 +1939,59 @@ class MasterConfig { const MasterConfig& get_default_master_config() { static MasterConfig config = [] { MasterConfig res; - res.add_config("testnet", R"abc({ - "liteservers": [ - ], - "validator": { - "@type": "validator.config.global", - "zero_state": { - "file_hash": "BzgfRpFgyNjHI7aR5KQhq4Wtr2wN+sXzLaW+rfHvP5A=", - "seqno": 0, - "root_hash": "WPsS1IiRjT0MSD6Xvys4QYQh7rrc9x0ybzXojwJ4gH0=", - "workchain": -1, - "shard": -9223372036854775808 - }, - "init_block":{ - "file_hash":"CXvKA37GFugspx6U7sv4Sh7KIVqR1R+Pj4AmGx2Ezi0=", - "seqno":2908533, - "root_hash":"oFi1uMHmELXV/AfjuvTZREmRY7TtNgq608sFjnRJCAo=", - "workchain":-1, - "shard":-9223372036854775808 - }, - "hardforks":[ - { - "file_hash":"x97xobbkPDggz7/u6KQzlT3pBmM5XfGE6vN7AiuTMU0=", - "seqno":1907338, - "root_hash":"BuZOCJvbg0ys2JBnfocqCf1T4rt0OzLLslOG3CjcSgU=", - "workchain":-1, - "shard":-9223372036854775808 - }, - { - "file_hash": "CXvKA37GFugspx6U7sv4Sh7KIVqR1R+Pj4AmGx2Ezi0=", - "seqno": 2908533, - "root_hash": "oFi1uMHmELXV/AfjuvTZREmRY7TtNgq608sFjnRJCAo=", - "workchain": -1, - "shard": -9223372036854775808 - } - ] - } -})abc"); res.add_config("mainnet", R"abc({ - "liteservers": [ - ], - "validator": { - "@type": "validator.config.global", - "zero_state": { - "workchain": -1, - "shard": -9223372036854775808, - "seqno": 0, - "root_hash": "F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=", - "file_hash": "XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24=" - }, - "init_block" : { - "root_hash": "irEt9whDfgaYwD+8AzBlYzrMZHhrkhSVp3PU1s4DOz4=", - "seqno": 10171687, - "file_hash": "lay/bUKUUFDJXU9S6gx9GACQFl+uK+zX8SqHWS9oLZc=", - "workchain": -1, - "shard": -9223372036854775808 - }, - "hardforks": [ - { - "file_hash": "t/9VBPODF7Zdh4nsnA49dprO69nQNMqYL+zk5bCjV/8=", - "seqno": 8536841, - "root_hash": "08Kpc9XxrMKC6BF/FeNHPS3MEL1/Vi/fQU/C9ELUrkc=", - "workchain": -1, - "shard": -9223372036854775808 - } - ] - } -})abc"); - res.add_config("testnet2", R"abc({ - "liteservers": [ - ], - "validator": { - "@type": "validator.config.global", - "zero_state": { - "workchain": -1, - "shard": -9223372036854775808, - "seqno": 0, - "root_hash": "F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=", - "file_hash": "XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24=" - }, - "init_block" : { - "root_hash": "irEt9whDfgaYwD+8AzBlYzrMZHhrkhSVp3PU1s4DOz4=", - "seqno": 10171687, - "file_hash": "lay/bUKUUFDJXU9S6gx9GACQFl+uK+zX8SqHWS9oLZc=", - "workchain": -1, - "shard": -9223372036854775808 - }, - "hardforks": [ - { - "file_hash": "t/9VBPODF7Zdh4nsnA49dprO69nQNMqYL+zk5bCjV/8=", - "seqno": 8536841, - "root_hash": "08Kpc9XxrMKC6BF/FeNHPS3MEL1/Vi/fQU/C9ELUrkc=", - "workchain": -1, - "shard": -9223372036854775808 - } - ] - } -})abc"); + "liteservers": [ + ], + "validator": { + "@type": "validator.config.global", + "zero_state": { + "workchain": -1, + "shard": -9223372036854775808, + "seqno": 0, + "root_hash": "F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=", + "file_hash": "XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24=" + }, + "init_block" : { + "root_hash": "irEt9whDfgaYwD+8AzBlYzrMZHhrkhSVp3PU1s4DOz4=", + "seqno": 10171687, + "file_hash": "lay/bUKUUFDJXU9S6gx9GACQFl+uK+zX8SqHWS9oLZc=", + "workchain": -1, + "shard": -9223372036854775808 + }, + "hardforks": [ + { + "file_hash": "t/9VBPODF7Zdh4nsnA49dprO69nQNMqYL+zk5bCjV/8=", + "seqno": 8536841, + "root_hash": "08Kpc9XxrMKC6BF/FeNHPS3MEL1/Vi/fQU/C9ELUrkc=", + "workchain": -1, + "shard": -9223372036854775808 + } + ] + } + })abc"); + res.add_config("testnet", R"abc({ + "liteservers": [ + ], + "validator": { + "@type": "validator.config.global", + "zero_state": { + "workchain": -1, + "shard": -9223372036854775808, + "seqno": 0, + "root_hash": "gj+B8wb/AmlPk1z1AhVI484rhrUpgSr2oSFIh56VoSg=", + "file_hash": "Z+IKwYS54DmmJmesw/nAD5DzWadnOCMzee+kdgSYDOg=" + }, + "init_block" : { + "root_hash": "gj+B8wb/AmlPk1z1AhVI484rhrUpgSr2oSFIh56VoSg=", + "seqno": 0, + "file_hash": "Z+IKwYS54DmmJmesw/nAD5DzWadnOCMzee+kdgSYDOg=", + "workchain": -1, + "shard": -9223372036854775808 + }, + "hardforks": [ + ] + } + })abc"); return res; }(); return config; @@ -2410,12 +2366,16 @@ auto to_any_promise(td::Promise&& promise) { } td::Status TonlibClient::do_request(const tonlib_api::raw_sendMessage& request, - td::Promise>&& promise) { + td::Promise>&& promise) { TRY_RESULT_PREFIX(body, vm::std_boc_deserialize(request.body_), TonlibError::InvalidBagOfCells("body")); std::ostringstream os; block::gen::t_Message_Any.print_ref(os, body); LOG(ERROR) << os.str(); - make_request(int_api::SendMessage{std::move(body)}, to_any_promise(std::move(promise))); + auto body_hash = body->get_hash().as_slice().str(); + make_request(int_api::SendMessage{std::move(body)}, + promise.wrap([body_hash = std::move(body_hash)](auto res) { + return tonlib_api::make_object(std::move(body_hash)); + })); return td::Status::OK(); } @@ -2667,11 +2627,10 @@ class GenericCreateSendGrams : public TonlibQueryActor { return downcast_call2(action, td::overloaded( [&](tonlib_api::dns_actionDeleteAll& del_all) -> R { - return ton::ManualDns::Action{"", 0, {}}; + return ton::ManualDns::Action{"", td::Bits256::zero(), {}}; }, [&](tonlib_api::dns_actionDelete& del) -> R { - TRY_RESULT(category, td::narrow_cast_safe(del.category_)); - return ton::ManualDns::Action{del.name_, category, {}}; + return ton::ManualDns::Action{del.name_, del.category_, {}}; }, [&](tonlib_api::dns_actionSet& set) -> R { if (!set.entry_) { @@ -2680,10 +2639,10 @@ class GenericCreateSendGrams : public TonlibQueryActor { if (!set.entry_->entry_) { return TonlibError::EmptyField("entry.entry"); } - TRY_RESULT(category, td::narrow_cast_safe(set.entry_->category_)); TRY_RESULT(entry_data, to_dns_entry_data(*set.entry_->entry_)); TRY_RESULT(data_cell, entry_data.as_cell()); - return ton::ManualDns::Action{set.entry_->name_, category, std::move(data_cell)}; + return ton::ManualDns::Action{set.entry_->name_, set.entry_->category_, + std::move(data_cell)}; })); } @@ -3673,30 +3632,30 @@ td::Result> to_tonlib_api( return res; } -void TonlibClient::finish_dns_resolve(std::string name, td::int32 category, td::int32 ttl, - td::optional block_id, DnsFinishData dns_finish_data, +void TonlibClient::finish_dns_resolve(std::string name, td::Bits256 category, td::int32 ttl, + td::optional block_id, block::StdAddress address, + DnsFinishData dns_finish_data, td::Promise>&& promise) { block_id = dns_finish_data.block_id; // TODO: check if the smartcontract supports Dns interface // TODO: should we use some DnsInterface instead of ManualDns? - auto dns = ton::ManualDns::create(dns_finish_data.smc_state); + auto dns = ton::ManualDns::create(dns_finish_data.smc_state, std::move(address)); TRY_RESULT_PROMISE(promise, entries, dns->resolve(name, category)); - if (entries.size() == 1 && entries[0].category == -1 && entries[0].name != name && ttl > 0 && - entries[0].data.type == ton::ManualDns::EntryData::Type::NextResolver) { + if (entries.size() == 1 && entries[0].partially_resolved && ttl > 0) { td::Slice got_name = entries[0].name; - if (got_name.size() >= name.size()) { + if (got_name.size() > name.size()) { TRY_STATUS_PROMISE(promise, TonlibError::Internal("domain is too long")); } - auto dot_position = name.size() - got_name.size() - 1; - auto suffix = name.substr(dot_position + 1); - auto prefix = name.substr(0, dot_position); - if (name[dot_position] != '.') { - TRY_STATUS_PROMISE(promise, td::Status::Error("next resolver error: domain split not at a component boundary ")); - } + auto suffix_start = name.size() - got_name.size(); + auto suffix = name.substr(suffix_start); if (suffix != got_name) { TRY_STATUS_PROMISE(promise, TonlibError::Internal("domain is not a suffix of the query")); } + auto prefix = name.substr(0, suffix_start); + if (!prefix.empty() && prefix.back() != '.' && suffix[0] != '.') { + TRY_STATUS_PROMISE(promise, td::Status::Error("next resolver error: domain split not at a component boundary ")); + } auto address = entries[0].data.data.get().resolver; return do_dns_request(prefix, category, ttl - 1, std::move(block_id), address, std::move(promise)); @@ -3711,12 +3670,13 @@ void TonlibClient::finish_dns_resolve(std::string name, td::int32 category, td:: promise.set_value(tonlib_api::make_object(std::move(api_entries))); } -void TonlibClient::do_dns_request(std::string name, td::int32 category, td::int32 ttl, +void TonlibClient::do_dns_request(std::string name, td::Bits256 category, td::int32 ttl, td::optional block_id, block::StdAddress address, td::Promise>&& promise) { auto block_id_copy = block_id.copy(); td::Promise new_promise = - promise.send_closure(actor_id(this), &TonlibClient::finish_dns_resolve, name, category, ttl, std::move(block_id)); + promise.send_closure(actor_id(this), &TonlibClient::finish_dns_resolve, name, category, ttl, std::move(block_id), + address); if (0) { make_request(int_api::GetAccountState{address, std::move(block_id_copy), {}}, @@ -3727,7 +3687,7 @@ void TonlibClient::do_dns_request(std::string name, td::int32 category, td::int3 return; } - TRY_RESULT_PROMISE(promise, args, ton::DnsInterface::resolve_args(name, category)); + TRY_RESULT_PROMISE(promise, args, ton::DnsInterface::resolve_args(name, category, address)); int_api::RemoteRunSmcMethod query; query.address = std::move(address); query.args = std::move(args); @@ -3749,8 +3709,12 @@ td::Status TonlibClient::do_request(const tonlib_api::dns_resolve& request, request.ttl_, std::move(block_id))); return td::Status::OK(); } + std::string name = request.name_; + if (name.empty() || name.back() != '.') { + name += '.'; + } TRY_RESULT(account_address, get_account_address(request.account_address_->account_address_)); - do_dns_request(request.name_, request.category_, request.ttl_, std::move(block_id), account_address, + do_dns_request(name, request.category_, request.ttl_, std::move(block_id), account_address, std::move(promise)); return td::Status::OK(); } diff --git a/tonlib/tonlib/TonlibClient.h b/tonlib/tonlib/TonlibClient.h index 716133e4..09c102cd 100644 --- a/tonlib/tonlib/TonlibClient.h +++ b/tonlib/tonlib/TonlibClient.h @@ -224,7 +224,7 @@ class TonlibClient : public td::actor::Actor { td::Status do_request(tonlib_api::options_setConfig& request, td::Promise>&& promise); - td::Status do_request(const tonlib_api::raw_sendMessage& request, td::Promise>&& promise); + td::Status do_request(const tonlib_api::raw_sendMessage& request, td::Promise>&& promise); td::Status do_request(const tonlib_api::raw_createAndSendMessage& request, td::Promise>&& promise); td::Status do_request(const tonlib_api::raw_createQuery& request, @@ -325,14 +325,15 @@ class TonlibClient : public td::actor::Actor { void perform_smc_execution(td::Ref smc, ton::SmartContract::Args args, td::Promise>&& promise); - void do_dns_request(std::string name, td::int32 category, td::int32 ttl, td::optional block_id, + void do_dns_request(std::string name, td::Bits256 category, td::int32 ttl, td::optional block_id, block::StdAddress address, td::Promise>&& promise); struct DnsFinishData { ton::BlockIdExt block_id; ton::SmartContract::State smc_state; }; - void finish_dns_resolve(std::string name, td::int32 category, td::int32 ttl, td::optional block_id, - DnsFinishData dns_finish_data, td::Promise>&& promise); + void finish_dns_resolve(std::string name, td::Bits256 category, td::int32 ttl, td::optional block_id, + block::StdAddress address, DnsFinishData dns_finish_data, + td::Promise>&& promise); td::Status do_request(int_api::GetAccountState request, td::Promise>&&); td::Status do_request(int_api::GetPrivateKey request, td::Promise&&); diff --git a/tonlib/tonlib/tonlib-cli.cpp b/tonlib/tonlib/tonlib-cli.cpp index 6b758fca..be550454 100644 --- a/tonlib/tonlib/tonlib-cli.cpp +++ b/tonlib/tonlib/tonlib-cli.cpp @@ -1162,7 +1162,7 @@ class TonlibCli : public td::actor::Actor { promise.set_error(td::Status::Error("Unknown command")); } - void do_dns_resolve(std::string name, td::int16 category, td::int32 ttl, + void do_dns_resolve(std::string name, td::Bits256 category, td::int32 ttl, tonlib_api::object_ptr resolved, td::Promise promise) { if (resolved->entries_.empty()) { td::TerminalIO::out() << "No dns entries found\n"; @@ -1192,11 +1192,12 @@ class TonlibCli : public td::actor::Actor { TRY_RESULT_PROMISE(promise, address, to_account_address(key_id, false)); auto name = parser.read_word(); auto category_str = parser.read_word(); - TRY_RESULT_PROMISE(promise, category, td::to_integer_safe(category_str)); + td::Bits256 category = category_str.empty() ? td::Bits256::zero() : td::sha256_bits256(td::as_slice(category_str)); std::vector> entries; entries.push_back(make_object( - "", -1, make_object(std::move(address.address)))); + "", ton::DNS_NEXT_RESOLVER_CATEGORY, + make_object(std::move(address.address)))); do_dns_resolve(name.str(), category, 10, make_object(std::move(entries)), std::move(promise)); } @@ -1217,8 +1218,8 @@ class TonlibCli : public td::actor::Actor { if (action.name.empty()) { actions.push_back(make_object()); td::TerminalIO::out() << "Delete all dns entries\n"; - } else if (action.category == 0) { - actions.push_back(make_object(action.name, 0)); + } else if (action.category.is_zero()) { + actions.push_back(make_object(action.name, td::Bits256::zero())); td::TerminalIO::out() << "Delete all dns enties with name: " << action.name << "\n"; } else if (!action.data) { actions.push_back(make_object(action.name, action.category)); @@ -1234,8 +1235,8 @@ class TonlibCli : public td::actor::Actor { TRY_RESULT_PROMISE(promise, data, tonlib::to_tonlib_api(action.data.value())); sb << action.data.value(); TRY_STATUS_PROMISE(promise, std::move(error)); - td::TerminalIO::out() << "Set dns entry: " << action.name << ":" << action.category << " " << sb.as_cslice() - << "\n"; + td::TerminalIO::out() << "Set dns entry: " << action.name << ":" << action.category << " " + << sb.as_cslice() << "\n"; actions.push_back(make_object( make_object(action.name, action.category, std::move(data)))); } diff --git a/tonlib/tonlib/tonlib_client_json.cpp b/tonlib/tonlib/tonlib_client_json.cpp index 243abce2..b6e25699 100644 --- a/tonlib/tonlib/tonlib_client_json.cpp +++ b/tonlib/tonlib/tonlib_client_json.cpp @@ -22,6 +22,8 @@ #include "td/utils/Slice.h" +#include "tonlib/Logging.h" + extern "C" int tonlib_client_json_square(int x, const char *str) { return x * x; } @@ -30,6 +32,10 @@ void *tonlib_client_json_create() { return new tonlib::ClientJson(); } +void tonlib_client_set_verbosity_level(int verbosity_level) { + tonlib::Logging::set_verbosity_level(verbosity_level); +} + void tonlib_client_json_destroy(void *client) { delete static_cast(client); } diff --git a/tonlib/tonlib/tonlib_client_json.h b/tonlib/tonlib/tonlib_client_json.h index d1784a1f..cb8ff2fb 100644 --- a/tonlib/tonlib/tonlib_client_json.h +++ b/tonlib/tonlib/tonlib_client_json.h @@ -26,6 +26,8 @@ extern "C" { TONLIBJSON_EXPORT void *tonlib_client_json_create(); +TONLIBJSON_EXPORT void tonlib_client_set_verbosity_level(int verbosity_level); + TONLIBJSON_EXPORT void tonlib_client_json_send(void *client, const char *request); TONLIBJSON_EXPORT const char *tonlib_client_json_receive(void *client, double timeout); diff --git a/tonlib/tonlibclientjson_export_list b/tonlib/tonlibclientjson_export_list index 217f3dd5..32735d33 100644 --- a/tonlib/tonlibclientjson_export_list +++ b/tonlib/tonlibclientjson_export_list @@ -3,3 +3,4 @@ _tonlib_client_json_destroy _tonlib_client_json_send _tonlib_client_json_receive _tonlib_client_json_execute +_tonlib_client_set_verbosity_level