1
0
Fork 0
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:
EmelyanenkoK 2022-08-04 17:45:31 +03:00
commit 5101b404a4
23 changed files with 488 additions and 399 deletions

13
.github/ISSUE_TEMPLATE.md vendored Normal file
View 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. -->

View 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

View file

@ -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

View file

@ -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;

View file

@ -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);
}

View file

@ -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

View file

@ -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];
}

View file

@ -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));

View file

@ -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);

View file

@ -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();

View file

@ -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 = "",

View file

@ -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) {

View file

@ -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);

View file

@ -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.

View file

@ -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();
}

View file

@ -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";

View file

@ -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();
}

View file

@ -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>&&);

View file

@ -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))));
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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