mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
rldp-http-proxy: use tonlib
- rldp-http-proxy used TONLib to resolve domains via DNS smartcontract - updated tonlib - bugfixes
This commit is contained in:
parent
1de39f5d7c
commit
493ae2410c
34 changed files with 816 additions and 153 deletions
|
@ -143,10 +143,9 @@ TEST(Tonlib, InitClose) {
|
|||
)abc";
|
||||
|
||||
sync_send(client, make_object<tonlib_api::options_setConfig>(cfg(bad_config.str()))).ensure_error();
|
||||
auto address =
|
||||
sync_send(client,
|
||||
make_object<tonlib_api::getAccountAddress>(make_object<tonlib_api::testGiver_initialAccountState>(), 0))
|
||||
.move_as_ok();
|
||||
auto address = sync_send(client, make_object<tonlib_api::getAccountAddress>(
|
||||
make_object<tonlib_api::testGiver_initialAccountState>(), 0))
|
||||
.move_as_ok();
|
||||
sync_send(client, make_object<tonlib_api::getAccountState>(std::move(address))).ensure_error();
|
||||
sync_send(client, make_object<tonlib_api::close>()).ensure();
|
||||
sync_send(client, make_object<tonlib_api::close>()).ensure_error();
|
||||
|
@ -490,6 +489,21 @@ TEST(Tonlib, KeysApi) {
|
|||
.move_as_ok();
|
||||
CHECK(new_imported_key->public_key_ == key->public_key_);
|
||||
CHECK(new_imported_key->secret_ != key->secret_);
|
||||
|
||||
auto exported_raw_key =
|
||||
sync_send(client, make_object<tonlib_api::exportUnencryptedKey>(make_object<tonlib_api::inputKeyRegular>(
|
||||
make_object<tonlib_api::key>(key->public_key_, new_imported_key->secret_.copy()),
|
||||
new_local_password.copy())))
|
||||
.move_as_ok();
|
||||
sync_send(client, make_object<tonlib_api::deleteKey>(
|
||||
make_object<tonlib_api::key>(new_imported_key->public_key_, new_imported_key->secret_.copy())))
|
||||
.move_as_ok();
|
||||
auto raw_imported_key = sync_send(client, make_object<tonlib_api::importUnencryptedKey>(new_local_password.copy(),
|
||||
std::move(exported_raw_key)))
|
||||
.move_as_ok();
|
||||
|
||||
CHECK(raw_imported_key->public_key_ == key->public_key_);
|
||||
CHECK(raw_imported_key->secret_ != key->secret_);
|
||||
}
|
||||
|
||||
TEST(Tonlib, ConfigCache) {
|
||||
|
|
|
@ -552,7 +552,7 @@ void dns_resolve(Client& client, const Wallet& dns, std::string name) {
|
|||
auto address = dns.get_address();
|
||||
while (true) {
|
||||
auto resolved =
|
||||
sync_send(client, make_object<::ton::tonlib_api::dns_resolve>(std::move(address), name, 1)).move_as_ok();
|
||||
sync_send(client, make_object<::ton::tonlib_api::dns_resolve>(std::move(address), name, 1, 0)).move_as_ok();
|
||||
CHECK(resolved->entries_.size() == 1);
|
||||
LOG(INFO) << to_string(resolved);
|
||||
if (resolved->entries_[0]->category_ == -1) {
|
||||
|
|
|
@ -179,6 +179,11 @@ td::Result<KeyStorage::ExportedEncryptedKey> KeyStorage::export_encrypted_key(In
|
|||
return ExportedEncryptedKey{std::move(res.encrypted_data)};
|
||||
}
|
||||
|
||||
td::Result<KeyStorage::ExportedUnencryptedKey> KeyStorage::export_unencrypted_key(InputKey input_key) {
|
||||
TRY_RESULT(decrypted_key, export_decrypted_key(std::move(input_key)));
|
||||
return ExportedUnencryptedKey{decrypted_key.private_key.as_octet_string()};
|
||||
}
|
||||
|
||||
td::Result<KeyStorage::Key> KeyStorage::import_encrypted_key(td::Slice local_password, td::Slice key_password,
|
||||
ExportedEncryptedKey exported_key) {
|
||||
EncryptedKey encrypted_key{std::move(exported_key.data), td::Ed25519::PublicKey(td::SecureString()),
|
||||
|
@ -187,6 +192,14 @@ td::Result<KeyStorage::Key> KeyStorage::import_encrypted_key(td::Slice local_pas
|
|||
return save_key(std::move(decrypted_key), local_password);
|
||||
}
|
||||
|
||||
td::Result<KeyStorage::Key> KeyStorage::import_unencrypted_key(td::Slice local_password,
|
||||
ExportedUnencryptedKey exported_key) {
|
||||
RawDecryptedKey raw_key;
|
||||
raw_key.private_key = std::move(exported_key.data);
|
||||
DecryptedKey key(std::move(raw_key));
|
||||
return save_key(std::move(key), local_password);
|
||||
}
|
||||
|
||||
KeyStorage::PrivateKey KeyStorage::fake_private_key() {
|
||||
return PrivateKey{td::SecureString(32, 0)};
|
||||
}
|
||||
|
|
|
@ -46,6 +46,9 @@ class KeyStorage {
|
|||
struct ExportedEncryptedKey {
|
||||
td::SecureString data;
|
||||
};
|
||||
struct ExportedUnencryptedKey {
|
||||
td::SecureString data;
|
||||
};
|
||||
struct PrivateKey {
|
||||
td::SecureString private_key;
|
||||
};
|
||||
|
@ -57,6 +60,7 @@ class KeyStorage {
|
|||
td::Result<ExportedKey> export_key(InputKey input_key);
|
||||
td::Result<ExportedPemKey> export_pem_key(InputKey input_key, td::Slice key_password);
|
||||
td::Result<ExportedEncryptedKey> export_encrypted_key(InputKey input_key, td::Slice key_password);
|
||||
td::Result<ExportedUnencryptedKey> export_unencrypted_key(InputKey input_key);
|
||||
td::Result<Key> change_local_password(InputKey input_key, td::Slice new_local_password);
|
||||
|
||||
td::Status delete_key(const Key& key);
|
||||
|
@ -66,6 +70,7 @@ class KeyStorage {
|
|||
td::Result<Key> import_pem_key(td::Slice local_password, td::Slice key_password, ExportedPemKey exported_key);
|
||||
td::Result<Key> import_encrypted_key(td::Slice local_password, td::Slice key_password,
|
||||
ExportedEncryptedKey exported_key);
|
||||
td::Result<Key> import_unencrypted_key(td::Slice local_password, ExportedUnencryptedKey exported_key);
|
||||
|
||||
td::Result<PrivateKey> load_private_key(InputKey input_key);
|
||||
|
||||
|
|
|
@ -353,6 +353,10 @@ class AccountState {
|
|||
return raw_.info.gen_utime;
|
||||
}
|
||||
|
||||
ton::BlockIdExt get_block_id() const {
|
||||
return raw_.block_id;
|
||||
}
|
||||
|
||||
td::int64 get_balance() const {
|
||||
return raw_.balance;
|
||||
}
|
||||
|
@ -2593,14 +2597,22 @@ 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::unique_ptr<AccountState> smc,
|
||||
void TonlibClient::finish_dns_resolve(std::string name, td::int32 category, td::int32 ttl,
|
||||
td::optional<ton::BlockIdExt> block_id, td::unique_ptr<AccountState> smc,
|
||||
td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise) {
|
||||
if (smc->get_wallet_type() != AccountState::WalletType::ManualDns) {
|
||||
return promise.set_error(TonlibError::AccountTypeUnexpected("ManualDns"));
|
||||
}
|
||||
block_id = smc->get_block_id();
|
||||
auto dns = ton::ManualDns::create(smc->get_smc_state());
|
||||
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) {
|
||||
auto address = entries[0].data.data.get<ton::ManualDns::EntryDataNextResolver>().resolver;
|
||||
return do_dns_request(name, category, ttl - 1, std::move(block_id), address, std::move(promise));
|
||||
}
|
||||
|
||||
std::vector<tonlib_api::object_ptr<tonlib_api::dns_entry>> api_entries;
|
||||
for (auto& entry : entries) {
|
||||
TRY_RESULT_PROMISE(promise, entry_data, to_tonlib_api(entry.data));
|
||||
|
@ -2610,21 +2622,27 @@ 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, block::StdAddress address,
|
||||
void TonlibClient::do_dns_request(std::string name, td::int32 category, td::int32 ttl,
|
||||
td::optional<ton::BlockIdExt> block_id, block::StdAddress address,
|
||||
td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise) {
|
||||
make_request(int_api::GetAccountState{address, query_context_.block_id.copy()},
|
||||
promise.send_closure(actor_id(this), &TonlibClient::finish_dns_resolve, name, category));
|
||||
auto block_id_copy = block_id.copy();
|
||||
make_request(int_api::GetAccountState{address, std::move(block_id_copy)},
|
||||
promise.send_closure(actor_id(this), &TonlibClient::finish_dns_resolve, name, category, ttl,
|
||||
std::move(block_id)));
|
||||
}
|
||||
|
||||
td::Status TonlibClient::do_request(const tonlib_api::dns_resolve& request,
|
||||
td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise) {
|
||||
auto block_id = query_context_.block_id.copy();
|
||||
if (!request.account_address_) {
|
||||
make_request(int_api::GetDnsResolver{},
|
||||
promise.send_closure(actor_id(this), &TonlibClient::do_dns_request, request.name_, request.category_));
|
||||
promise.send_closure(actor_id(this), &TonlibClient::do_dns_request, request.name_, request.category_,
|
||||
request.ttl_, std::move(block_id)));
|
||||
return td::Status::OK();
|
||||
}
|
||||
TRY_RESULT(account_address, get_account_address(request.account_address_->account_address_));
|
||||
do_dns_request(request.name_, request.category_, account_address, std::move(promise));
|
||||
do_dns_request(request.name_, request.category_, request.ttl_, std::move(block_id), account_address,
|
||||
std::move(promise));
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
|
@ -2745,6 +2763,28 @@ td::Status TonlibClient::do_request(const tonlib_api::importEncryptedKey& reques
|
|||
promise.set_value(tonlib_api::make_object<tonlib_api::key>(key_bytes.serialize(true), std::move(key.secret)));
|
||||
return td::Status::OK();
|
||||
}
|
||||
td::Status TonlibClient::do_request(const tonlib_api::exportUnencryptedKey& request,
|
||||
td::Promise<object_ptr<tonlib_api::exportedUnencryptedKey>>&& promise) {
|
||||
if (!request.input_key_) {
|
||||
return TonlibError::EmptyField("input_key");
|
||||
}
|
||||
TRY_RESULT(input_key, from_tonlib(*request.input_key_));
|
||||
TRY_RESULT(exported_key, key_storage_.export_unencrypted_key(std::move(input_key)));
|
||||
promise.set_value(tonlib_api::make_object<tonlib_api::exportedUnencryptedKey>(std::move(exported_key.data)));
|
||||
return td::Status::OK();
|
||||
}
|
||||
td::Status TonlibClient::do_request(const tonlib_api::importUnencryptedKey& request,
|
||||
td::Promise<object_ptr<tonlib_api::key>>&& promise) {
|
||||
if (!request.exported_unencrypted_key_) {
|
||||
return TonlibError::EmptyField("exported_encrypted_key");
|
||||
}
|
||||
TRY_RESULT(key, key_storage_.import_unencrypted_key(
|
||||
std::move(request.local_password_),
|
||||
KeyStorage::ExportedUnencryptedKey{std::move(request.exported_unencrypted_key_->data_)}));
|
||||
TRY_RESULT(key_bytes, public_key_from_bytes(key.public_key.as_slice()));
|
||||
promise.set_value(tonlib_api::make_object<tonlib_api::key>(key_bytes.serialize(true), std::move(key.secret)));
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
td::Status TonlibClient::do_request(const tonlib_api::changeLocalPassword& request,
|
||||
td::Promise<object_ptr<tonlib_api::key>>&& promise) {
|
||||
|
|
|
@ -245,6 +245,11 @@ class TonlibClient : public td::actor::Actor {
|
|||
td::Status do_request(const tonlib_api::importEncryptedKey& request,
|
||||
td::Promise<object_ptr<tonlib_api::key>>&& promise);
|
||||
|
||||
td::Status do_request(const tonlib_api::exportUnencryptedKey& request,
|
||||
td::Promise<object_ptr<tonlib_api::exportedUnencryptedKey>>&& promise);
|
||||
td::Status do_request(const tonlib_api::importUnencryptedKey& request,
|
||||
td::Promise<object_ptr<tonlib_api::key>>&& promise);
|
||||
|
||||
td::Status do_request(const tonlib_api::changeLocalPassword& request,
|
||||
td::Promise<object_ptr<tonlib_api::key>>&& promise);
|
||||
|
||||
|
@ -290,9 +295,10 @@ class TonlibClient : public td::actor::Actor {
|
|||
|
||||
td::Status do_request(const tonlib_api::dns_resolve& request,
|
||||
td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise);
|
||||
void do_dns_request(std::string name, td::int32 category, block::StdAddress address,
|
||||
td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise);
|
||||
void finish_dns_resolve(std::string name, td::int32 category, td::unique_ptr<AccountState> smc,
|
||||
void do_dns_request(std::string name, td::int32 category, td::int32 ttl, td::optional<ton::BlockIdExt> block_id,
|
||||
block::StdAddress address, td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise);
|
||||
void finish_dns_resolve(std::string name, td::int32 category, td::int32 ttl, td::optional<ton::BlockIdExt> block_id,
|
||||
td::unique_ptr<AccountState> smc,
|
||||
td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise);
|
||||
|
||||
td::Status do_request(int_api::GetAccountState request, td::Promise<td::unique_ptr<AccountState>>&&);
|
||||
|
|
|
@ -114,6 +114,7 @@ class TonlibCli : public td::actor::Actor {
|
|||
bool use_callbacks_for_network{false};
|
||||
td::int32 wallet_version = 2;
|
||||
td::int32 wallet_revision = 0;
|
||||
td::optional<td::uint32> wallet_id;
|
||||
bool ignore_cache{false};
|
||||
|
||||
bool one_shot{false};
|
||||
|
@ -223,7 +224,11 @@ class TonlibCli : public td::actor::Actor {
|
|||
LOG_IF(ERROR, r_ok.is_error()) << r_ok.error();
|
||||
if (r_ok.is_ok()) {
|
||||
if (r_ok.ok()->config_info_) {
|
||||
wallet_id_ = static_cast<td::uint32>(r_ok.ok()->config_info_->default_wallet_id_);
|
||||
if (options_.wallet_id) {
|
||||
wallet_id_ = options_.wallet_id.value();
|
||||
} else {
|
||||
wallet_id_ = static_cast<td::uint32>(r_ok.ok()->config_info_->default_wallet_id_);
|
||||
}
|
||||
}
|
||||
td::TerminalIO::out() << "Tonlib is inited\n";
|
||||
if (options_.one_shot) {
|
||||
|
@ -307,12 +312,13 @@ class TonlibCli : public td::actor::Actor {
|
|||
"<addr> with specified parameters\n";
|
||||
td::TerminalIO::out() << "getstate <key_id>\tget state of wallet with requested key\n";
|
||||
td::TerminalIO::out() << "getaddress <key_id>\tget address of wallet with requested key\n";
|
||||
td::TerminalIO::out() << "dns resove <addr> <name>\n";
|
||||
td::TerminalIO::out() << "dns resolve (<addr> | root) <name> <category>\n";
|
||||
td::TerminalIO::out() << "dns cmd <key_id> <dns_cmd>\n";
|
||||
//td::TerminalIO::out() << "dns cmdlist <key_id> {<dns_cmd>\\n} end\n";
|
||||
td::TerminalIO::out() << "dns cmdfile <key_id> <file>\n";
|
||||
td::TerminalIO::out() << "\t<dns_cmd> = set <name> <category> <data> | delete.name <name> | delete.all\n";
|
||||
td::TerminalIO::out() << "\t<data> = DELETED | EMPTY | TEXT:<text>\n";
|
||||
td::TerminalIO::out() << "\t<data> = DELETED | EMPTY | TEXT:<text> | NEXT:<smc-address> | SMC:<smc-address> | "
|
||||
"ADNL:<adnl-address>\n";
|
||||
|
||||
td::TerminalIO::out()
|
||||
<< "blockmode auto|manual\tWith auto mode, all queries will be executed with respect to the latest block. "
|
||||
|
@ -331,6 +337,7 @@ class TonlibCli : public td::actor::Actor {
|
|||
td::TerminalIO::out() << "setbounceble <address> [<bounceble>] - change bounceble flag in address\n";
|
||||
td::TerminalIO::out() << "importkey - import key\n";
|
||||
td::TerminalIO::out() << "importkeypem <filename> - import key\n";
|
||||
td::TerminalIO::out() << "importkeyraw <filename> - import key\n";
|
||||
td::TerminalIO::out() << "deletekeys - delete ALL PRIVATE KEYS\n";
|
||||
td::TerminalIO::out() << "exportkey [<key_id>] - export key\n";
|
||||
td::TerminalIO::out() << "exportkeypem [<key_id>] - export key\n";
|
||||
|
@ -403,6 +410,8 @@ class TonlibCli : public td::actor::Actor {
|
|||
get_address(parser.read_word(), std::move(cmd_promise));
|
||||
} else if (cmd == "importkeypem") {
|
||||
import_key_pem(parser.read_word(), std::move(cmd_promise));
|
||||
} else if (cmd == "importkeyraw") {
|
||||
import_key_raw(parser.read_word(), std::move(cmd_promise));
|
||||
} else if (cmd == "dns") {
|
||||
run_dns_cmd(parser, std::move(cmd_promise));
|
||||
} else if (cmd == "gethistory") {
|
||||
|
@ -442,16 +451,21 @@ class TonlibCli : public td::actor::Actor {
|
|||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
if (resolved->entries_[0]->entry_->get_id() == tonlib_api::dns_entryDataNextResolver::ID) {
|
||||
if (resolved->entries_[0]->entry_->get_id() == tonlib_api::dns_entryDataNextResolver::ID && ttl != 0) {
|
||||
td::TerminalIO::out() << "Redirect resolver\n";
|
||||
auto entry = tonlib_api::move_object_as<tonlib_api::dns_entryDataNextResolver>(resolved->entries_[0]->entry_);
|
||||
send_query(tonlib_api::make_object<tonlib_api::dns_resolve>(std::move(entry->resolver_), name, category),
|
||||
promise.send_closure(actor_id(this), &TonlibCli::do_dns_resolve, name, category, ttl));
|
||||
send_query(tonlib_api::make_object<tonlib_api::dns_resolve>(std::move(entry->resolver_), name, category, ttl),
|
||||
promise.send_closure(actor_id(this), &TonlibCli::do_dns_resolve, name, category, 0));
|
||||
return;
|
||||
}
|
||||
promise.set_error(td::Status::Error("Failed to resolve"));
|
||||
}
|
||||
|
||||
void dns_resolve(td::ConstParser& parser, td::Promise<td::Unit> promise) {
|
||||
auto key_id = parser.read_word();
|
||||
if (key_id == "root") {
|
||||
key_id = "none";
|
||||
}
|
||||
TRY_RESULT_PROMISE(promise, address, to_account_address(key_id, false));
|
||||
auto name = parser.read_word();
|
||||
auto category_str = parser.read_word();
|
||||
|
@ -1198,6 +1212,22 @@ class TonlibCli : public td::actor::Actor {
|
|||
return td::Unit();
|
||||
}));
|
||||
}
|
||||
void import_key_raw(td::Slice filename, td::Promise<td::Unit> promise) {
|
||||
TRY_RESULT_PROMISE(promise, data, td::read_file_secure(filename.str()));
|
||||
using tonlib_api::make_object;
|
||||
send_query(make_object<tonlib_api::importUnencryptedKey>(
|
||||
td::SecureString(), make_object<tonlib_api::exportedUnencryptedKey>(std::move(data))),
|
||||
promise.wrap([&](auto&& key) {
|
||||
LOG(ERROR) << to_string(key);
|
||||
KeyInfo info;
|
||||
info.public_key = key->public_key_;
|
||||
info.secret = std::move(key->secret_);
|
||||
keys_.push_back(std::move(info));
|
||||
export_key("exportkey", key->public_key_, keys_.size() - 1, td::SecureString());
|
||||
store_keys();
|
||||
return td::Unit();
|
||||
}));
|
||||
}
|
||||
|
||||
void export_key(std::string cmd, std::string key, size_t key_i, td::Slice password) {
|
||||
using tonlib_api::make_object;
|
||||
|
@ -1485,6 +1515,11 @@ int main(int argc, char* argv[]) {
|
|||
options.use_callbacks_for_network = true;
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('w', "wallet-id", "do not use this", [&](td::Slice arg) {
|
||||
TRY_RESULT(wallet_id, td::to_integer_safe<td::uint32>((arg)));
|
||||
options.wallet_id = wallet_id;
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('W', "wallet-version", "do not use this (version[.revision])", [&](td::Slice arg) {
|
||||
td::ConstParser parser(arg);
|
||||
TRY_RESULT(version, td::to_integer_safe<td::int32>((parser.read_till_nofail('.'))));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue