mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
update tonlib
tonlib: update collator: increased collation speed for masterchain fift: bugfixes
This commit is contained in:
parent
7ea00ebfcf
commit
dd745485e2
27 changed files with 313 additions and 172 deletions
|
@ -434,9 +434,10 @@ TEST(Tonlib, KeysApi) {
|
|||
using tonlib_api::make_object;
|
||||
Client client;
|
||||
|
||||
td::mkdir("testdir").ignore();
|
||||
// init
|
||||
sync_send(client, make_object<tonlib_api::init>(
|
||||
make_object<tonlib_api::options>(nullptr, make_object<tonlib_api::keyStoreTypeDirectory>("."))))
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(
|
||||
nullptr, make_object<tonlib_api::keyStoreTypeDirectory>("testdir"))))
|
||||
.ensure();
|
||||
auto local_password = td::SecureString("local password");
|
||||
auto mnemonic_password = td::SecureString("mnemonic password");
|
||||
|
|
|
@ -61,15 +61,14 @@ class ExtClient {
|
|||
auto raw_query = ton::serialize_tl_object(&query, true);
|
||||
td::uint32 tag = td::Random::fast_uint32();
|
||||
VLOG(lite_server) << "send query to liteserver: " << tag << " " << to_string(query);
|
||||
td::BufferSlice liteserver_query =
|
||||
ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_query>(std::move(raw_query)), true);
|
||||
|
||||
if (seq_no >= 0) {
|
||||
auto wait = ton::lite_api::liteServer_waitMasterchainSeqno(seq_no, 5000);
|
||||
VLOG(lite_server) << " with prefix " << to_string(wait);
|
||||
auto prefix = ton::serialize_tl_object(&wait, true);
|
||||
liteserver_query = td::BufferSlice(PSLICE() << prefix.as_slice() << liteserver_query.as_slice());
|
||||
raw_query = td::BufferSlice(PSLICE() << prefix.as_slice() << raw_query.as_slice());
|
||||
}
|
||||
td::BufferSlice liteserver_query =
|
||||
ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_query>(std::move(raw_query)), true);
|
||||
|
||||
send_raw_query(
|
||||
std::move(liteserver_query), [promise = std::move(promise), tag](td::Result<td::BufferSlice> R) mutable {
|
||||
|
|
|
@ -69,7 +69,7 @@ td::Result<DecryptedKey> KeyStorage::export_decrypted_key(InputKey input_key) {
|
|||
if (r_encrypted_data.is_error()) {
|
||||
r_encrypted_data = kv_->get(to_file_name_old(input_key.key));
|
||||
if (r_encrypted_data.is_ok()) {
|
||||
LOG(WARNING) << "Restore private from deprecated location " << to_file_name_old(input_key.key) << " --> "
|
||||
LOG(WARNING) << "Restore private key from deprecated location " << to_file_name_old(input_key.key) << " --> "
|
||||
<< to_file_name(input_key.key);
|
||||
TRY_STATUS_PREFIX(kv_->set(to_file_name(input_key.key), r_encrypted_data.ok()), TonlibError::Internal());
|
||||
kv_->erase(to_file_name_old(input_key.key)).ignore();
|
||||
|
@ -78,6 +78,21 @@ td::Result<DecryptedKey> KeyStorage::export_decrypted_key(InputKey input_key) {
|
|||
TRY_RESULT_PREFIX(encrypted_data, std::move(r_encrypted_data), TonlibError::KeyUnknown());
|
||||
EncryptedKey encrypted_key{std::move(encrypted_data), td::Ed25519::PublicKey(std::move(input_key.key.public_key)),
|
||||
std::move(input_key.key.secret)};
|
||||
{
|
||||
auto r_decrypted_key = encrypted_key.decrypt(input_key.local_password.copy(), true, true);
|
||||
if (r_decrypted_key.is_ok()) {
|
||||
LOG(WARNING) << "Restore private from deprecated encryption " << to_file_name(input_key.key);
|
||||
auto decrypted_key = r_decrypted_key.move_as_ok();
|
||||
auto key = Key{encrypted_key.public_key.as_octet_string(), encrypted_key.secret.copy()};
|
||||
auto new_encrypted_key = decrypted_key.encrypt(input_key.local_password.copy(), encrypted_key.secret);
|
||||
CHECK(new_encrypted_key.public_key.as_octet_string() == encrypted_key.public_key.as_octet_string());
|
||||
CHECK(new_encrypted_key.secret == encrypted_key.secret);
|
||||
CHECK(new_encrypted_key.decrypt(input_key.local_password.copy()).ok().private_key.as_octet_string() ==
|
||||
decrypted_key.private_key.as_octet_string());
|
||||
kv_->set(to_file_name(key), new_encrypted_key.encrypted_data);
|
||||
return std::move(decrypted_key);
|
||||
}
|
||||
}
|
||||
TRY_RESULT_PREFIX(decrypted_key, encrypted_key.decrypt(std::move(input_key.local_password)),
|
||||
TonlibError::KeyDecrypt());
|
||||
return std::move(decrypted_key);
|
||||
|
@ -139,14 +154,9 @@ td::Result<KeyStorage::ExportedPemKey> KeyStorage::export_pem_key(InputKey input
|
|||
}
|
||||
|
||||
td::Result<KeyStorage::Key> KeyStorage::change_local_password(InputKey input_key, td::Slice new_local_password) {
|
||||
auto new_secret =
|
||||
DecryptedKey::change_local_password(input_key.key.secret, input_key.local_password, new_local_password);
|
||||
Key res;
|
||||
res.public_key = std::move(input_key.key.public_key);
|
||||
res.secret = std::move(new_secret);
|
||||
TRY_RESULT_PREFIX(value, kv_->get(to_file_name(input_key.key)), TonlibError::KeyUnknown());
|
||||
TRY_STATUS_PREFIX(kv_->add(to_file_name(res), value), TonlibError::Internal());
|
||||
return std::move(res);
|
||||
auto old_name = to_file_name(input_key.key);
|
||||
TRY_RESULT(decrypted_key, export_decrypted_key(std::move(input_key)));
|
||||
return save_key(std::move(decrypted_key), new_local_password);
|
||||
}
|
||||
|
||||
td::Result<KeyStorage::Key> KeyStorage::import_pem_key(td::Slice local_password, td::Slice key_password,
|
||||
|
|
|
@ -39,7 +39,7 @@ class KeyValueDir : public KeyValue {
|
|||
}
|
||||
|
||||
td::Status erase(td::Slice key) override {
|
||||
return td::unlink(key.str());
|
||||
return td::unlink(to_file_path(key.str()));
|
||||
}
|
||||
|
||||
void foreach_key(std::function<void(td::Slice)> f) override {
|
||||
|
|
|
@ -32,7 +32,8 @@ namespace tonlib {
|
|||
//
|
||||
td::StringBuilder& operator<<(td::StringBuilder& sb, const LastBlockState& state) {
|
||||
return sb << td::tag("last_block", state.last_block_id.to_str())
|
||||
<< td::tag("last_key_block", state.last_key_block_id.to_str()) << td::tag("utime", state.utime);
|
||||
<< td::tag("last_key_block", state.last_key_block_id.to_str()) << td::tag("utime", state.utime)
|
||||
<< td::tag("init_block", state.init_block_id.to_str());
|
||||
}
|
||||
|
||||
LastBlock::LastBlock(ExtClientRef client, LastBlockState state, Config config, td::unique_ptr<Callback> callback)
|
||||
|
@ -40,8 +41,7 @@ LastBlock::LastBlock(ExtClientRef client, LastBlockState state, Config config, t
|
|||
client_.set_client(client);
|
||||
state_.last_block_id = state_.last_key_block_id;
|
||||
|
||||
VLOG(last_block) << "check_init_block: skip - FIXME before release";
|
||||
check_init_block_state_ = QueryState::Done;
|
||||
VLOG(last_block) << "State: " << state_;
|
||||
}
|
||||
|
||||
void LastBlock::get_last_block(td::Promise<LastBlockState> promise) {
|
||||
|
@ -87,7 +87,7 @@ void LastBlock::sync_loop() {
|
|||
} else {
|
||||
check_init_block_state_ = QueryState::Active;
|
||||
check_init_block_stats_.start();
|
||||
if (state_.last_block_id.id.seqno >= config_.init_block_id.id.seqno) {
|
||||
if (state_.last_key_block_id.id.seqno >= config_.init_block_id.id.seqno) {
|
||||
VLOG(last_block) << "check_init_block: start - init_block -> last_block";
|
||||
do_check_init_block(config_.init_block_id, state_.last_key_block_id);
|
||||
} else {
|
||||
|
@ -162,10 +162,18 @@ void LastBlock::update_state(block::BlockProofChain& chain) {
|
|||
update_utime(chain.last_utime);
|
||||
}
|
||||
if (is_changed) {
|
||||
callback_->on_state_changed(state_);
|
||||
save_state();
|
||||
}
|
||||
}
|
||||
|
||||
void LastBlock::save_state() {
|
||||
if (check_init_block_state_ != QueryState::Done) {
|
||||
VLOG(last_block) << "skip `save_state` because `check_init_block` is not finished";
|
||||
return;
|
||||
}
|
||||
callback_->on_state_changed(state_);
|
||||
}
|
||||
|
||||
void LastBlock::on_block_proof(
|
||||
ton::BlockIdExt from,
|
||||
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof>> r_block_proof) {
|
||||
|
@ -209,6 +217,9 @@ void LastBlock::on_init_block_proof(
|
|||
if (chain->complete) {
|
||||
VLOG(last_block) << "check_init_block: done\n" << check_init_block_stats_;
|
||||
check_init_block_state_ = QueryState::Done;
|
||||
if (update_init_block(config_.init_block_id)) {
|
||||
save_state();
|
||||
}
|
||||
sync_loop();
|
||||
} else {
|
||||
do_check_init_block(chain->to, to);
|
||||
|
@ -291,6 +302,22 @@ bool LastBlock::update_mc_last_key_block(ton::BlockIdExt mc_key_block_id) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool LastBlock::update_init_block(ton::BlockIdExt init_block_id) {
|
||||
if (has_fatal_error()) {
|
||||
return false;
|
||||
}
|
||||
if (!init_block_id.is_valid()) {
|
||||
LOG(ERROR) << "Ignore invalid init block";
|
||||
return false;
|
||||
}
|
||||
if (state_.init_block_id != init_block_id) {
|
||||
state_.init_block_id = init_block_id;
|
||||
LOG(INFO) << "Update init block id: " << state_.init_block_id.to_str();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LastBlock::update_utime(td::int64 utime) {
|
||||
if (state_.utime < utime) {
|
||||
state_.utime = utime;
|
||||
|
|
|
@ -201,7 +201,9 @@ class LastBlock : public td::actor::Actor {
|
|||
bool update_mc_last_block(ton::BlockIdExt mc_block_id);
|
||||
bool update_mc_last_key_block(ton::BlockIdExt mc_key_block_id);
|
||||
void update_utime(td::int64 utime);
|
||||
bool update_init_block(ton::BlockIdExt init_block_id);
|
||||
|
||||
void save_state();
|
||||
void on_sync_ok();
|
||||
void on_sync_error(td::Status status);
|
||||
void on_fatal_error(td::Status status);
|
||||
|
|
|
@ -108,7 +108,6 @@ class GetTransactionHistory : public td::actor::Actor {
|
|||
|
||||
void check(td::Status status) {
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << status;
|
||||
promise_.set_error(std::move(status));
|
||||
stop();
|
||||
}
|
||||
|
@ -208,7 +207,7 @@ class GetRawAccountState : public td::actor::Actor {
|
|||
auto cell = res.info.root;
|
||||
std::ostringstream outp;
|
||||
block::gen::t_Account.print_ref(outp, cell);
|
||||
LOG(ERROR) << outp.str();
|
||||
LOG(INFO) << outp.str();
|
||||
if (cell.is_null()) {
|
||||
return res;
|
||||
}
|
||||
|
@ -682,8 +681,9 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_accountState>> to_raw_accountS
|
|||
.as_slice()
|
||||
.str();
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::raw_accountState>(
|
||||
raw_state.balance, std::move(code), std::move(data), to_transaction_id(raw_state.info), raw_state.info.gen_utime);
|
||||
return tonlib_api::make_object<tonlib_api::raw_accountState>(raw_state.balance, std::move(code), std::move(data),
|
||||
to_transaction_id(raw_state.info), raw_state.frozen_hash,
|
||||
raw_state.info.gen_utime);
|
||||
}
|
||||
|
||||
td::Result<std::string> to_std_address_or_throw(td::Ref<vm::CellSlice> cs) {
|
||||
|
@ -803,7 +803,7 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_transaction>> to_raw_transacti
|
|||
|
||||
std::ostringstream outp;
|
||||
block::gen::t_Transaction.print_ref(outp, info.transaction);
|
||||
LOG(ERROR) << outp.str();
|
||||
LOG(INFO) << outp.str();
|
||||
|
||||
auto is_just = trans.r1.in_msg->prefetch_long(1);
|
||||
if (is_just == trans.r1.in_msg->fetch_long_eof) {
|
||||
|
@ -917,7 +917,7 @@ td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> to_generic_
|
|||
if (raw_state.code.is_null()) {
|
||||
return tonlib_api::make_object<tonlib_api::generic_accountStateUninited>(
|
||||
tonlib_api::make_object<tonlib_api::uninited_accountState>(raw_state.balance, to_transaction_id(raw_state.info),
|
||||
raw_state.info.gen_utime));
|
||||
raw_state.frozen_hash, raw_state.info.gen_utime));
|
||||
}
|
||||
|
||||
auto code_hash = raw_state.code->prefetch_ref()->get_hash();
|
||||
|
@ -953,7 +953,6 @@ td::Status TonlibClient::do_request(const tonlib_api::raw_sendMessage& request,
|
|||
client_.send_query(ton::lite_api::liteServer_sendMessage(vm::std_boc_serialize(message).move_as_ok()),
|
||||
[promise = std::move(promise)](auto r_info) mutable {
|
||||
TRY_RESULT_PROMISE(promise, info, std::move(r_info));
|
||||
LOG(ERROR) << "info: " << to_string(info);
|
||||
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
|
||||
});
|
||||
return td::Status::OK();
|
||||
|
@ -1042,7 +1041,6 @@ td::Status TonlibClient::do_request(const tonlib_api::testWallet_sendGrams& requ
|
|||
return TonlibError::MessageTooLong();
|
||||
}
|
||||
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
||||
account_address.bounceable = false;
|
||||
TRY_RESULT(input_key, from_tonlib(*request.private_key_));
|
||||
auto address = GenericAccount::get_address(
|
||||
0 /*zerochain*/, TestWallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())));
|
||||
|
@ -1116,7 +1114,6 @@ td::Status TonlibClient::do_request(const tonlib_api::wallet_sendGrams& request,
|
|||
TRY_RESULT_PREFIX(valid_until, td::narrow_cast_safe<td::uint32>(request.valid_until_),
|
||||
TonlibError::InvalidField("valid_until", "overflow"));
|
||||
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
||||
account_address.bounceable = false;
|
||||
TRY_RESULT(input_key, from_tonlib(*request.private_key_));
|
||||
auto address = GenericAccount::get_address(
|
||||
0 /*zerochain*/, Wallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())));
|
||||
|
@ -1168,7 +1165,6 @@ td::Status TonlibClient::do_request(const tonlib_api::testGiver_sendGrams& reque
|
|||
return TonlibError::MessageTooLong();
|
||||
}
|
||||
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
||||
account_address.bounceable = false;
|
||||
auto message = TestGiver::make_a_gift_message(request.seqno_, request.amount_, request.message_, account_address);
|
||||
auto message_hash = message->get_hash().as_slice().str();
|
||||
td::Promise<object_ptr<tonlib_api::ok>> new_promise =
|
||||
|
@ -1245,7 +1241,7 @@ class GenericSendGrams : public TonlibQueryActor {
|
|||
block::StdAddress source_address_;
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::generic_AccountState> destination_state_;
|
||||
bool is_destination_bounce_{false};
|
||||
bool is_destination_bounceable_{false};
|
||||
|
||||
void check(td::Status status) {
|
||||
if (status.is_error()) {
|
||||
|
@ -1263,7 +1259,7 @@ class GenericSendGrams : public TonlibQueryActor {
|
|||
return TonlibError::EmptyField("destination");
|
||||
}
|
||||
TRY_RESULT(destination_address, get_account_address(send_grams_.destination_->account_address_));
|
||||
is_destination_bounce_ = destination_address.bounceable;
|
||||
is_destination_bounceable_ = destination_address.bounceable;
|
||||
|
||||
if (!send_grams_.source_) {
|
||||
return TonlibError::EmptyField("destination");
|
||||
|
@ -1333,9 +1329,23 @@ class GenericSendGrams : public TonlibQueryActor {
|
|||
td::Status do_on_destination_state(td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> r_state) {
|
||||
TRY_RESULT(state, std::move(r_state));
|
||||
destination_state_ = std::move(state);
|
||||
if (destination_state_->get_id() == tonlib_api::generic_accountStateUninited::ID && is_destination_bounce_ &&
|
||||
!send_grams_.allow_send_to_uninited_) {
|
||||
return TonlibError::DangerousTransaction("Transfer to uninited wallet");
|
||||
if (destination_state_->get_id() == tonlib_api::generic_accountStateUninited::ID && is_destination_bounceable_) {
|
||||
//FIXME: after restoration of frozen accounts will be supported
|
||||
if (!static_cast<tonlib_api::generic_accountStateUninited&>(*destination_state_)
|
||||
.account_state_->frozen_hash_.empty()) {
|
||||
return TonlibError::TransferToFrozen();
|
||||
//return TonlibError::DangerousTransaction("Transfer to frozen wallet");
|
||||
}
|
||||
if (send_grams_.allow_send_to_uninited_) {
|
||||
TRY_RESULT(destination_address, get_account_address(send_grams_.destination_->account_address_));
|
||||
destination_address.bounceable = false;
|
||||
auto new_destination_address = destination_address.rserialize(true);
|
||||
LOG(INFO) << "Change destination address from bounceable to non-bounceable "
|
||||
<< send_grams_.destination_->account_address_ << " -> " << new_destination_address;
|
||||
send_grams_.destination_->account_address_ = std::move(new_destination_address);
|
||||
} else {
|
||||
return TonlibError::DangerousTransaction("Transfer to uninited wallet");
|
||||
}
|
||||
}
|
||||
return do_loop();
|
||||
}
|
||||
|
|
|
@ -128,6 +128,9 @@ struct TonlibError {
|
|||
static td::Status NotEnoughFunds() {
|
||||
return td::Status::Error(500, "NOT_ENOUGH_FUNDS");
|
||||
}
|
||||
static td::Status TransferToFrozen() {
|
||||
return td::Status::Error(500, "TRANSFER_TO_FROZEN");
|
||||
}
|
||||
|
||||
static td::Status LiteServer(td::int32 code, td::Slice message) {
|
||||
auto f = [&](td::Slice code_description) { return LiteServer(code, code_description, message); };
|
||||
|
|
|
@ -35,36 +35,15 @@ DecryptedKey::DecryptedKey(RawDecryptedKey key)
|
|||
: DecryptedKey(std::move(key.mnemonic_words), td::Ed25519::PrivateKey(key.private_key.copy())) {
|
||||
}
|
||||
|
||||
td::SecureString DecryptedKey::change_local_password(td::Slice secret_str, td::Slice old_local_password,
|
||||
td::Slice new_local_password) {
|
||||
CHECK(secret_str.size() == 32);
|
||||
td::SecureString old_local_password_hash(32);
|
||||
sha256(old_local_password, old_local_password_hash.as_mutable_slice());
|
||||
td::SecureString new_local_password_hash(32);
|
||||
sha256(new_local_password, new_local_password_hash.as_mutable_slice());
|
||||
|
||||
td::SecureString new_secret(32);
|
||||
for (size_t i = 0; i < new_secret.size(); i++) {
|
||||
new_secret.as_mutable_slice()[i] =
|
||||
secret_str[i] ^ old_local_password_hash.as_slice()[i] ^ new_local_password_hash.as_slice()[i];
|
||||
}
|
||||
return new_secret;
|
||||
}
|
||||
|
||||
EncryptedKey DecryptedKey::encrypt(td::Slice local_password, td::Slice old_secret) const {
|
||||
LOG(ERROR) << "encrypt";
|
||||
td::SecureString secret(32);
|
||||
if (old_secret.size() == td::as_slice(secret).size()) {
|
||||
secret.as_mutable_slice().copy_from(old_secret);
|
||||
} else {
|
||||
td::Random::secure_bytes(secret.as_mutable_slice());
|
||||
}
|
||||
td::SecureString local_password_hash(32);
|
||||
sha256(local_password, local_password_hash.as_mutable_slice());
|
||||
td::SecureString decrypted_secret(32);
|
||||
for (size_t i = 0; i < decrypted_secret.size(); i++) {
|
||||
decrypted_secret.as_mutable_slice()[i] = secret.as_slice()[i] ^ local_password_hash.as_slice()[i];
|
||||
}
|
||||
hmac_sha256(secret, local_password, decrypted_secret.as_mutable_slice());
|
||||
|
||||
td::SecureString encryption_secret(64);
|
||||
pbkdf2_sha512(as_slice(decrypted_secret), "TON local key", EncryptedKey::PBKDF_ITERATIONS,
|
||||
|
|
|
@ -56,8 +56,6 @@ struct DecryptedKey {
|
|||
std::vector<td::SecureString> mnemonic_words;
|
||||
td::Ed25519::PrivateKey private_key;
|
||||
|
||||
static td::SecureString change_local_password(td::Slice secret, td::Slice old_local_password,
|
||||
td::Slice new_local_password);
|
||||
EncryptedKey encrypt(td::Slice local_password, td::Slice secret = {}) const;
|
||||
};
|
||||
|
||||
|
|
|
@ -24,15 +24,19 @@
|
|||
#include "td/utils/crypto.h"
|
||||
|
||||
namespace tonlib {
|
||||
td::Result<DecryptedKey> EncryptedKey::decrypt(td::Slice local_password, bool check_public_key) {
|
||||
td::Result<DecryptedKey> EncryptedKey::decrypt(td::Slice local_password, bool check_public_key, bool old) const {
|
||||
if (secret.size() != 32) {
|
||||
return td::Status::Error("Failed to decrypt key: invalid secret size");
|
||||
}
|
||||
td::SecureString local_password_hash(32);
|
||||
sha256(local_password, local_password_hash.as_mutable_slice());
|
||||
td::SecureString decrypted_secret(32);
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
decrypted_secret.as_mutable_slice()[i] = secret.as_slice()[i] ^ local_password_hash.as_slice()[i];
|
||||
if (old) {
|
||||
td::SecureString local_password_hash(32);
|
||||
sha256(local_password, local_password_hash.as_mutable_slice());
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
decrypted_secret.as_mutable_slice()[i] = secret.as_slice()[i] ^ local_password_hash.as_slice()[i];
|
||||
}
|
||||
} else {
|
||||
hmac_sha256(secret, local_password, decrypted_secret.as_mutable_slice());
|
||||
}
|
||||
|
||||
td::SecureString encryption_secret(64);
|
||||
|
|
|
@ -32,7 +32,7 @@ struct EncryptedKey {
|
|||
td::Ed25519::PublicKey public_key;
|
||||
td::SecureString secret;
|
||||
|
||||
td::Result<DecryptedKey> decrypt(td::Slice local_password, bool check_public_key = true);
|
||||
td::Result<DecryptedKey> decrypt(td::Slice local_password, bool check_public_key = true, bool old = false) const;
|
||||
};
|
||||
|
||||
} // namespace tonlib
|
||||
|
|
|
@ -186,11 +186,21 @@ class TonlibCli : public td::actor::Actor {
|
|||
if (cmd.empty()) {
|
||||
return;
|
||||
}
|
||||
auto to_bool = [](td::Slice word, bool def = false) {
|
||||
if (word.empty()) {
|
||||
return def;
|
||||
}
|
||||
if (word == "0" || word == "FALSE" || word == "false") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (cmd == "help") {
|
||||
td::TerminalIO::out() << "help - show this help\n";
|
||||
td::TerminalIO::out() << "genkey - generate new secret key\n";
|
||||
td::TerminalIO::out() << "keys - show all stored keys\n";
|
||||
td::TerminalIO::out() << "unpackaddress <address> - validate and parse address\n";
|
||||
td::TerminalIO::out() << "setbounceble <address> [<bounceble>] - change bounceble flag in address\n";
|
||||
td::TerminalIO::out() << "importkey - import key\n";
|
||||
td::TerminalIO::out() << "deletekeys - delete ALL PRIVATE KEYS\n";
|
||||
td::TerminalIO::out() << "exportkey [<key_id>] - export key\n";
|
||||
|
@ -214,6 +224,8 @@ class TonlibCli : public td::actor::Actor {
|
|||
try_stop();
|
||||
} else if (cmd == "keys") {
|
||||
dump_keys();
|
||||
} else if (cmd == "deletekey") {
|
||||
//delete_key(parser.read_word());
|
||||
} else if (cmd == "deletekeys") {
|
||||
delete_all_keys();
|
||||
} else if (cmd == "exportkey") {
|
||||
|
@ -223,15 +235,6 @@ class TonlibCli : public td::actor::Actor {
|
|||
} else if (cmd == "setconfig") {
|
||||
auto config = parser.read_word();
|
||||
auto name = parser.read_word();
|
||||
auto to_bool = [](td::Slice word) {
|
||||
if (word.empty()) {
|
||||
return false;
|
||||
}
|
||||
if (word == "0" || word == "FALSE" || word == "false") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
auto use_callback = parser.read_word();
|
||||
auto force = parser.read_word();
|
||||
set_config(config, name, to_bool(use_callback), to_bool(force));
|
||||
|
@ -251,6 +254,10 @@ class TonlibCli : public td::actor::Actor {
|
|||
get_hints(parser.read_word());
|
||||
} else if (cmd == "unpackaddress") {
|
||||
unpack_address(parser.read_word());
|
||||
} else if (cmd == "setbounceable") {
|
||||
auto addr = parser.read_word();
|
||||
auto bounceable = parser.read_word();
|
||||
set_bounceable(addr, to_bool(bounceable, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,6 +332,26 @@ class TonlibCli : public td::actor::Actor {
|
|||
});
|
||||
}
|
||||
|
||||
void set_bounceable(td::Slice addr, bool bounceable) {
|
||||
send_query(tonlib_api::make_object<tonlib_api::unpackAccountAddress>(addr.str()),
|
||||
[addr = addr.str(), bounceable, this](auto r_parsed_addr) mutable {
|
||||
if (r_parsed_addr.is_error()) {
|
||||
LOG(ERROR) << "Failed to parse address: " << r_parsed_addr.error();
|
||||
return;
|
||||
}
|
||||
auto parsed_addr = r_parsed_addr.move_as_ok();
|
||||
parsed_addr->bounceable_ = bounceable;
|
||||
this->send_query(tonlib_api::make_object<tonlib_api::packAccountAddress>(std::move(parsed_addr)),
|
||||
[](auto r_addr) mutable {
|
||||
if (r_addr.is_error()) {
|
||||
LOG(ERROR) << "Failed to pack address";
|
||||
return;
|
||||
}
|
||||
td::TerminalIO::out() << r_addr.ok()->account_address_ << "\n";
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void generate_key(td::SecureString entropy = {}) {
|
||||
if (entropy.size() < 20) {
|
||||
td::TerminalIO::out() << "Enter some entropy";
|
||||
|
@ -527,6 +554,25 @@ class TonlibCli : public td::actor::Actor {
|
|||
return std::move(res);
|
||||
}
|
||||
|
||||
void delete_key(td::Slice key) {
|
||||
auto r_key_i = to_key_i(key);
|
||||
if (r_key_i.is_error()) {
|
||||
td::TerminalIO::out() << "Unknown key id: [" << key << "]\n";
|
||||
return;
|
||||
}
|
||||
using tonlib_api::make_object;
|
||||
auto key_i = r_key_i.move_as_ok();
|
||||
send_query(make_object<tonlib_api::deleteKey>(
|
||||
make_object<tonlib_api::key>(keys_[key_i].public_key, keys_[key_i].secret.copy())),
|
||||
|
||||
[key = key.str()](auto r_res) {
|
||||
if (r_res.is_error()) {
|
||||
td::TerminalIO::out() << "Can't delete key id: [" << key << "] " << r_res.error() << "\n";
|
||||
return;
|
||||
}
|
||||
td::TerminalIO::out() << "Ok\n";
|
||||
});
|
||||
}
|
||||
void export_key(td::Slice key) {
|
||||
if (key.empty()) {
|
||||
dump_keys();
|
||||
|
@ -754,6 +800,11 @@ class TonlibCli : public td::actor::Actor {
|
|||
}
|
||||
void transfer(Address from, Address to, td::uint64 grams, td::Slice password, td::Slice message,
|
||||
bool allow_send_to_uninited) {
|
||||
auto r_sz = td::to_integer_safe<td::size_t>(message);
|
||||
auto msg = message.str();
|
||||
if (r_sz.is_ok()) {
|
||||
msg = std::string(r_sz.ok(), 'Z');
|
||||
}
|
||||
using tonlib_api::make_object;
|
||||
auto key = !from.secret.empty()
|
||||
? make_object<tonlib_api::inputKey>(
|
||||
|
@ -761,7 +812,7 @@ class TonlibCli : public td::actor::Actor {
|
|||
: nullptr;
|
||||
send_query(
|
||||
make_object<tonlib_api::generic_sendGrams>(std::move(key), std::move(from.address), std::move(to.address),
|
||||
grams, 30, allow_send_to_uninited, message.str()),
|
||||
grams, 60, allow_send_to_uninited, std::move(msg)),
|
||||
[this](auto r_res) {
|
||||
if (r_res.is_error()) {
|
||||
td::TerminalIO::out() << "Can't transfer: " << r_res.error() << "\n";
|
||||
|
@ -881,6 +932,10 @@ int main(int argc, char* argv[]) {
|
|||
options.config = std::move(data);
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('N', "config-name", "set lite server config name", [&](td::Slice arg) {
|
||||
options.name = arg.str();
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('n', "use-callbacks-for-network", "do not use this", [&]() {
|
||||
options.use_callbacks_for_network = true;
|
||||
return td::Status::OK();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue