mirror of
https://github.com/ton-blockchain/ton
synced 2025-02-14 12:12:21 +00:00
Merge branch 'master' into testnet
This commit is contained in:
commit
5101b404a4
23 changed files with 488 additions and 399 deletions
13
.github/ISSUE_TEMPLATE.md
vendored
Normal file
13
.github/ISSUE_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!-- Describe the issue -->
|
||||
<!--- What behavior did you expect? -->
|
||||
|
||||
<!--- What was the actual behavior? -->
|
||||
|
||||
<!--- How reliably can you reproduce the issue, what are the steps to do so? -->
|
||||
|
||||
<!-- What version of TON are you using, where did you get it (github actions, self-compiled, etc)? -->
|
||||
|
||||
<!-- What type of machine are you observing the error on (OS/CPU and disk type)? -->
|
||||
|
||||
<!-- Any extra information that might be useful in the debugging process. -->
|
||||
<!--- This is normally the contents of a `debug.log` or `config.log` file. Raw text or a link to a pastebin type site are preferred. -->
|
40
.github/workflows/ubuntu-18.04-compile.yml
vendored
Normal file
40
.github/workflows/ubuntu-18.04-compile.yml
vendored
Normal file
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -146,24 +146,27 @@ td::Result<DnsInterface::EntryData> 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<SmartContract::Args> DnsInterface::resolve_args(td::Slice name, td::int32 category_big) {
|
||||
TRY_RESULT(category, td::narrow_cast_safe<td::int16>(category_big));
|
||||
td::Result<SmartContract::Args> 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<std::vector<DnsInterface::Entry>> DnsInterface::resolve(td::Slice name, td::int32 category) const {
|
||||
td::Result<std::vector<DnsInterface::Entry>> DnsInterface::resolve(td::Slice name, td::Bits256 category) const {
|
||||
TRY_RESULT(raw_entries, resolve_raw(name, category));
|
||||
std::vector<Entry> entries;
|
||||
entries.reserve(raw_entries.size());
|
||||
|
@ -171,10 +174,15 @@ td::Result<std::vector<DnsInterface::Entry>> 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<std::vector<DnsInterface::Entry>> DnsInterface::resolve(td::Slice nam
|
|||
Inline [Name] structure: [UInt<6b>:length] [Bytes<lengthB>: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<td::uint32> ManualDns::get_wallet_id_or_throw() const {
|
|||
return static_cast<td::uint32>(vm::load_cell_slice(state_.data).fetch_ulong(32));
|
||||
}
|
||||
|
||||
td::Result<td::Ref<vm::Cell>> ManualDns::create_set_value_unsigned(td::int16 category, td::Slice name,
|
||||
td::Result<td::Ref<vm::Cell>> ManualDns::create_set_value_unsigned(td::Bits256 category, td::Slice name,
|
||||
td::Ref<vm::Cell> 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<td::Ref<vm::Cell>> ManualDns::create_delete_value_unsigned(td::int16 category, td::Slice name) const {
|
||||
td::Result<td::Ref<vm::Cell>> 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<td::Ref<vm::Cell>> ManualDns::create_set_all_unsigned(td::Span<Action
|
|||
if (o_dict.not_null()) {
|
||||
o_dict->prefetch_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<td::Ref<vm::Cell>> 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<std::vector<ManualDns::RawEntry>> ManualDns::resolve_raw(td::Slice name, td::int32 category_big) const {
|
||||
return TRY_VM(resolve_raw_or_throw(name, category_big));
|
||||
td::Result<std::vector<ManualDns::RawEntry>> ManualDns::resolve_raw(td::Slice name, td::Bits256 category) const {
|
||||
return TRY_VM(resolve_raw_or_throw(name, category));
|
||||
}
|
||||
td::Result<std::vector<ManualDns::RawEntry>> ManualDns::resolve_raw_or_throw(td::Slice name,
|
||||
td::int32 category_big) const {
|
||||
TRY_RESULT(category, td::narrow_cast_safe<td::int16>(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<std::vector<ManualDns::RawEntry>> 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<td::int16>(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<td::Ref<vm::Cell>> ManualDns::create_update_query(CombinedActions<Act
|
|||
}
|
||||
return create_set_all_unsigned(combined.actions.value());
|
||||
}
|
||||
if (combined.category == 0) {
|
||||
if (combined.category.is_zero()) {
|
||||
if (!combined.actions) {
|
||||
return create_delete_name_unsigned(encode_name(combined.name));
|
||||
}
|
||||
|
@ -488,9 +496,13 @@ td::Result<td::Ref<vm::Cell>> 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::ActionExt> 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<td::int16>(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);
|
||||
}
|
||||
|
|
|
@ -26,10 +26,14 @@
|
|||
#include "smc-envelope/SmartContract.h"
|
||||
|
||||
#include "Ed25519.h"
|
||||
#include "common/checksum.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
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<vm::Cell> data;
|
||||
td::Bits256 category;
|
||||
td::Ref<vm::CellSlice> data;
|
||||
bool partially_resolved = false;
|
||||
};
|
||||
|
||||
struct ActionExt {
|
||||
std::string name;
|
||||
td::int16 category;
|
||||
td::Bits256 category;
|
||||
td::optional<EntryData> data;
|
||||
static td::Result<ActionExt> parse(td::Slice);
|
||||
};
|
||||
|
||||
struct Action {
|
||||
std::string name;
|
||||
td::int16 category;
|
||||
td::Bits256 category;
|
||||
td::optional<td::Ref<vm::Cell>> data;
|
||||
|
||||
bool does_create_category() const {
|
||||
CHECK(!name.empty());
|
||||
CHECK(category != 0);
|
||||
CHECK(!category.is_zero());
|
||||
return static_cast<bool>(data);
|
||||
}
|
||||
bool does_change_empty() const {
|
||||
CHECK(!name.empty());
|
||||
CHECK(category != 0);
|
||||
CHECK(!category.is_zero());
|
||||
return static_cast<bool>(data) && data.value().not_null();
|
||||
}
|
||||
void make_non_empty() {
|
||||
CHECK(!name.empty());
|
||||
CHECK(category != 0);
|
||||
CHECK(!category.is_zero());
|
||||
if (!data) {
|
||||
data = td::Ref<vm::Cell>();
|
||||
}
|
||||
}
|
||||
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 << "<null>";
|
||||
|
@ -156,15 +162,14 @@ class DnsInterface {
|
|||
}
|
||||
};
|
||||
|
||||
virtual ~DnsInterface() {
|
||||
}
|
||||
virtual ~DnsInterface() = default;
|
||||
virtual size_t get_max_name_size() const = 0;
|
||||
virtual td::Result<std::vector<RawEntry>> resolve_raw(td::Slice name, td::int32 category) const = 0;
|
||||
virtual td::Result<std::vector<RawEntry>> resolve_raw(td::Slice name, td::Bits256 category) const = 0;
|
||||
virtual td::Result<td::Ref<vm::Cell>> create_update_query(
|
||||
td::Ed25519::PrivateKey& pk, td::Span<Action> actions,
|
||||
td::uint32 valid_until = std::numeric_limits<td::uint32>::max()) const = 0;
|
||||
|
||||
td::Result<std::vector<Entry>> resolve(td::Slice name, td::int32 category) const;
|
||||
td::Result<std::vector<Entry>> 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<SmartContract::Args> 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<SmartContract::Args> 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<ManualDns> create(State state) {
|
||||
return td::Ref<ManualDns>(true, std::move(state));
|
||||
static td::Ref<ManualDns> create(State state, block::StdAddress address = {}) {
|
||||
return td::Ref<ManualDns>(true, std::move(state), std::move(address));
|
||||
}
|
||||
static td::Ref<ManualDns> create(td::Ref<vm::Cell> data = {}, int revision = 0);
|
||||
static td::Ref<ManualDns> 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<td::uint32> get_wallet_id() const;
|
||||
td::Result<td::uint32> get_wallet_id_or_throw() const;
|
||||
|
||||
td::Result<td::Ref<vm::Cell>> create_set_value_unsigned(td::int16 category, td::Slice name,
|
||||
td::Result<td::Ref<vm::Cell>> create_set_value_unsigned(td::Bits256 category, td::Slice name,
|
||||
td::Ref<vm::Cell> data) const;
|
||||
td::Result<td::Ref<vm::Cell>> create_delete_value_unsigned(td::int16 category, td::Slice name) const;
|
||||
td::Result<td::Ref<vm::Cell>> create_delete_value_unsigned(td::Bits256 category, td::Slice name) const;
|
||||
td::Result<td::Ref<vm::Cell>> create_delete_all_unsigned() const;
|
||||
td::Result<td::Ref<vm::Cell>> create_set_all_unsigned(td::Span<Action> entries) const;
|
||||
td::Result<td::Ref<vm::Cell>> create_delete_name_unsigned(td::Slice name) const;
|
||||
|
@ -222,8 +230,8 @@ class ManualDns : public ton::SmartContract, public DnsInterface {
|
|||
static td::Ref<vm::Cell> create_init_data_fast(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id);
|
||||
|
||||
size_t get_max_name_size() const override;
|
||||
td::Result<std::vector<RawEntry>> resolve_raw(td::Slice name, td::int32 category_big) const override;
|
||||
td::Result<std::vector<RawEntry>> resolve_raw_or_throw(td::Slice name, td::int32 category_big) const;
|
||||
td::Result<std::vector<RawEntry>> resolve_raw(td::Slice name, td::Bits256 category) const override;
|
||||
td::Result<std::vector<RawEntry>> resolve_raw_or_throw(td::Slice name, td::Bits256 category) const;
|
||||
|
||||
td::Result<td::Ref<vm::Cell>> create_init_query(
|
||||
const td::Ed25519::PrivateKey& private_key,
|
||||
|
@ -235,10 +243,10 @@ class ManualDns : public ton::SmartContract, public DnsInterface {
|
|||
template <class ActionT>
|
||||
struct CombinedActions {
|
||||
std::string name;
|
||||
td::int16 category{0};
|
||||
td::Bits256 category = td::Bits256::zero();
|
||||
td::optional<std::vector<ActionT>> 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 << "<data>" << action.actions.value().size();
|
||||
} else {
|
||||
|
@ -251,7 +259,7 @@ class ManualDns : public ton::SmartContract, public DnsInterface {
|
|||
template <class ActionT = Action>
|
||||
static std::vector<CombinedActions<ActionT>> combine_actions(td::Span<ActionT> actions) {
|
||||
struct Info {
|
||||
std::set<td::int16> known_category;
|
||||
std::set<td::Bits256> known_category;
|
||||
std::vector<ActionT> 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<td::Ref<vm::Cell>> create_update_query(CombinedActions<Action>& combined) const;
|
||||
private:
|
||||
block::StdAddress address_;
|
||||
};
|
||||
|
||||
} // namespace ton
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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<std::string> text;
|
||||
|
||||
bool does_create_category() const {
|
||||
CHECK(!name.empty());
|
||||
CHECK(category != 0);
|
||||
CHECK(!category.is_zero());
|
||||
return static_cast<bool>(text);
|
||||
}
|
||||
bool does_change_empty() const {
|
||||
CHECK(!name.empty());
|
||||
CHECK(category != 0);
|
||||
CHECK(!category.is_zero());
|
||||
return static_cast<bool>(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() : "<empty>")
|
||||
<< "]";
|
||||
return sb << "[" << entry.name << ":" << entry.category.to_hex() << ":"
|
||||
<< (entry.text ? entry.text.value() : "<empty>") << "]";
|
||||
}
|
||||
};
|
||||
void update(td::Span<Action> 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<Entry> resolve(td::Slice name, td::int16 category) {
|
||||
std::vector<Entry> resolve(td::Slice name, td::Bits256 category) {
|
||||
std::vector<Entry> 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::string, std::map<td::int16, std::string>, std::less<>> entries_;
|
||||
std::map<std::string, std::map<td::Bits256, std::string>, 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<Entry> resolve(td::Slice name, td::int16 category) {
|
||||
LOG(ERROR) << "RESOLVE: " << name << " " << category;
|
||||
std::vector<Entry> 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<Action> actions;
|
||||
|
@ -1130,7 +1136,7 @@ void do_dns_test(CheckedDns&& dns) {
|
|||
if (rnd.fast(0, 20) == 0) {
|
||||
return action;
|
||||
}
|
||||
action.category = td::narrow_cast<td::int16>(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<td::int16>(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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <unistd.h>
|
||||
|
@ -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<std::string> 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<vm::Cell> 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<vm::StackEntry> 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<std::vector<vm::StackEntry>> 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<vm::Cell> value, bool raw_dump) {
|
||||
bool TestNode::show_dns_record(std::ostream& os, td::Bits256 cat, Ref<vm::CellSlice> 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<vm::Cell> 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<vm::Cell> 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<vm::Cell> 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<vm::CellSlice> 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::CellSlice>() : 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();
|
||||
|
|
|
@ -213,13 +213,13 @@ class TestNode : public td::actor::Actor {
|
|||
bool register_config_param1(Ref<vm::Cell> value);
|
||||
bool register_config_param4(Ref<vm::Cell> 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<vm::Cell> value);
|
||||
bool show_dns_record(std::ostream& os, int cat, Ref<vm::Cell> value, bool raw_dump);
|
||||
bool show_dns_record(std::ostream& os, td::Bits256 cat, Ref<vm::CellSlice> 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 = "",
|
||||
|
|
|
@ -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<tonlib_api::dns_resolve>(nullptr, host_, 0, 16);
|
||||
td::Bits256 category = td::sha256_bits256(td::Slice("site", 4));
|
||||
auto obj = tonlib_api::make_object<tonlib_api::dns_resolve>(nullptr, host_, category, 16);
|
||||
|
||||
auto P =
|
||||
td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<tonlib_api::object_ptr<tonlib_api::Object>> R) {
|
||||
|
|
|
@ -74,11 +74,11 @@ int main() {
|
|||
generate_cpp<td::TD_TL_writer_jni_cpp, td::TD_TL_writer_jni_h>(
|
||||
"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\""},
|
||||
{"<string>", "\"td/utils/SharedSlice.h\""});
|
||||
{"<string>", "\"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\""},
|
||||
{"<string>", "\"td/utils/SharedSlice.h\""});
|
||||
{"<string>", "\"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);
|
||||
|
|
|
@ -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.message> = raw.Transaction;
|
||||
raw.transactions transactions:vector<raw.transaction> 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.entry> = 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<tvm.StackEntry> = 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;
|
||||
|
|
Binary file not shown.
|
@ -575,83 +575,92 @@ TEST(Tonlib, ConfigCache) {
|
|||
nullptr, make_object<tonlib_api::keyStoreTypeDirectory>("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<tonlib_api::options_validateConfig>(make_object<tonlib_api::config>(bad, "", true, false)))
|
||||
.ensure_error();
|
||||
|
||||
sync_send(client,
|
||||
make_object<tonlib_api::options_validateConfig>(make_object<tonlib_api::config>(mainnet, "", true, false)))
|
||||
.ensure();
|
||||
sync_send(client,
|
||||
make_object<tonlib_api::options_validateConfig>(make_object<tonlib_api::config>(testnet, "", true, false)))
|
||||
.ensure();
|
||||
sync_send(client,
|
||||
make_object<tonlib_api::options_validateConfig>(make_object<tonlib_api::config>(testnet2, "", true, false)))
|
||||
.ensure();
|
||||
sync_send(client,
|
||||
make_object<tonlib_api::options_validateConfig>(make_object<tonlib_api::config>(testnet3, "", true, false)))
|
||||
make_object<tonlib_api::options_validateConfig>(make_object<tonlib_api::config>(custom, "", true, false)))
|
||||
.ensure();
|
||||
|
||||
sync_send(client, make_object<tonlib_api::options_validateConfig>(
|
||||
make_object<tonlib_api::config>(testnet2, "testnet", true, false)))
|
||||
make_object<tonlib_api::config>(mainnet, "testnet", true, false)))
|
||||
.ensure_error();
|
||||
|
||||
sync_send(client, make_object<tonlib_api::options_setConfig>(
|
||||
make_object<tonlib_api::config>(testnet2, "testnet2", true, false)))
|
||||
make_object<tonlib_api::config>(testnet, "testnet", true, false)))
|
||||
.ensure();
|
||||
sync_send(client, make_object<tonlib_api::options_setConfig>(
|
||||
make_object<tonlib_api::config>(testnet3, "testnet2", true, false)))
|
||||
make_object<tonlib_api::config>(custom, "testnet", true, false)))
|
||||
.ensure_error();
|
||||
}
|
||||
|
|
|
@ -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<object_ptr<dns_Action>> actions;
|
||||
|
||||
actions.push_back(make_object<dns_actionSet>(
|
||||
make_object<dns_entry>("A", -1, make_object<dns_entryDataNextResolver>(A_B.get_address()))));
|
||||
make_object<dns_entry>("A", ton::DNS_NEXT_RESOLVER_CATEGORY,
|
||||
make_object<dns_entryDataNextResolver>(A_B.get_address()))));
|
||||
auto init_A = create_update_dns_query(client, A, std::move(actions)).move_as_ok();
|
||||
actions.push_back(make_object<dns_actionSet>(
|
||||
make_object<dns_entry>("B", -1, make_object<dns_entryDataNextResolver>(A_B_C.get_address()))));
|
||||
make_object<dns_entry>("B", ton::DNS_NEXT_RESOLVER_CATEGORY,
|
||||
make_object<dns_entryDataNextResolver>(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<dns_actionSet>(make_object<dns_entry>("C", 1, make_object<dns_entryDataText>("Hello dns"))));
|
||||
make_object<dns_actionSet>(make_object<dns_entry>("C", td::sha256_bits256(td::Slice("cat", 3)),
|
||||
make_object<dns_entryDataText>("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";
|
||||
|
|
|
@ -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<td::Unit>&& promise) {
|
|||
}
|
||||
|
||||
td::Status TonlibClient::do_request(const tonlib_api::raw_sendMessage& request,
|
||||
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
|
||||
td::Promise<object_ptr<tonlib_api::raw_extMessageInfo>>&& 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<tonlib_api::raw_extMessageInfo>(std::move(body_hash));
|
||||
}));
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
|
@ -2667,11 +2627,10 @@ class GenericCreateSendGrams : public TonlibQueryActor {
|
|||
return downcast_call2<R>(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<td::int16>(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<td::int16>(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<tonlib_api::object_ptr<tonlib_api::dns_EntryData>> to_tonlib_api(
|
|||
return res;
|
||||
}
|
||||
|
||||
void TonlibClient::finish_dns_resolve(std::string name, td::int32 category, td::int32 ttl,
|
||||
td::optional<ton::BlockIdExt> block_id, DnsFinishData dns_finish_data,
|
||||
void TonlibClient::finish_dns_resolve(std::string name, td::Bits256 category, td::int32 ttl,
|
||||
td::optional<ton::BlockIdExt> block_id, block::StdAddress address,
|
||||
DnsFinishData dns_finish_data,
|
||||
td::Promise<object_ptr<tonlib_api::dns_resolved>>&& 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<ton::ManualDns::EntryDataNextResolver>().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<tonlib_api::dns_resolved>(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<ton::BlockIdExt> block_id, block::StdAddress address,
|
||||
td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise) {
|
||||
auto block_id_copy = block_id.copy();
|
||||
td::Promise<DnsFinishData> 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();
|
||||
}
|
||||
|
|
|
@ -224,7 +224,7 @@ class TonlibClient : public td::actor::Actor {
|
|||
td::Status do_request(tonlib_api::options_setConfig& request,
|
||||
td::Promise<object_ptr<tonlib_api::options_configInfo>>&& promise);
|
||||
|
||||
td::Status do_request(const tonlib_api::raw_sendMessage& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise);
|
||||
td::Status do_request(const tonlib_api::raw_sendMessage& request, td::Promise<object_ptr<tonlib_api::raw_extMessageInfo>>&& promise);
|
||||
td::Status do_request(const tonlib_api::raw_createAndSendMessage& request,
|
||||
td::Promise<object_ptr<tonlib_api::ok>>&& 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<ton::SmartContract> smc, ton::SmartContract::Args args,
|
||||
td::Promise<object_ptr<tonlib_api::smc_runResult>>&& promise);
|
||||
|
||||
void do_dns_request(std::string name, td::int32 category, td::int32 ttl, td::optional<ton::BlockIdExt> block_id,
|
||||
void do_dns_request(std::string name, td::Bits256 category, td::int32 ttl, td::optional<ton::BlockIdExt> block_id,
|
||||
block::StdAddress address, td::Promise<object_ptr<tonlib_api::dns_resolved>>&& 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<ton::BlockIdExt> block_id,
|
||||
DnsFinishData dns_finish_data, td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise);
|
||||
void finish_dns_resolve(std::string name, td::Bits256 category, td::int32 ttl, td::optional<ton::BlockIdExt> block_id,
|
||||
block::StdAddress address, DnsFinishData dns_finish_data,
|
||||
td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise);
|
||||
|
||||
td::Status do_request(int_api::GetAccountState request, td::Promise<td::unique_ptr<AccountState>>&&);
|
||||
td::Status do_request(int_api::GetPrivateKey request, td::Promise<KeyStorage::PrivateKey>&&);
|
||||
|
|
|
@ -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<tonlib_api::dns_resolved> resolved, td::Promise<td::Unit> 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<td::int16>(category_str));
|
||||
td::Bits256 category = category_str.empty() ? td::Bits256::zero() : td::sha256_bits256(td::as_slice(category_str));
|
||||
|
||||
std::vector<tonlib_api::object_ptr<tonlib_api::dns_entry>> entries;
|
||||
entries.push_back(make_object<tonlib_api::dns_entry>(
|
||||
"", -1, make_object<tonlib_api::dns_entryDataNextResolver>(std::move(address.address))));
|
||||
"", ton::DNS_NEXT_RESOLVER_CATEGORY,
|
||||
make_object<tonlib_api::dns_entryDataNextResolver>(std::move(address.address))));
|
||||
do_dns_resolve(name.str(), category, 10, make_object<tonlib_api::dns_resolved>(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<tonlib_api::dns_actionDeleteAll>());
|
||||
td::TerminalIO::out() << "Delete all dns entries\n";
|
||||
} else if (action.category == 0) {
|
||||
actions.push_back(make_object<tonlib_api::dns_actionDelete>(action.name, 0));
|
||||
} else if (action.category.is_zero()) {
|
||||
actions.push_back(make_object<tonlib_api::dns_actionDelete>(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<tonlib_api::dns_actionDelete>(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<tonlib_api::dns_actionSet>(
|
||||
make_object<tonlib_api::dns_entry>(action.name, action.category, std::move(data))));
|
||||
}
|
||||
|
|
|
@ -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<tonlib::ClientJson *>(client);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue