1
0
Fork 0
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:
ton 2020-02-12 00:14:16 +04:00
parent 1de39f5d7c
commit 493ae2410c
34 changed files with 816 additions and 153 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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