mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated smartcontract code
updated lite-client and configuration smartcontract updated tonlib code
This commit is contained in:
parent
8e5bd938aa
commit
bce33f588a
46 changed files with 677 additions and 299 deletions
|
@ -132,6 +132,12 @@ TEST(Tonlib, TestGiver) {
|
|||
vm::CellSlice(vm::NoVm(), res).print_rec(std::cerr);
|
||||
CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == res->get_hash());
|
||||
}
|
||||
TEST(Tonlib, PublicKey) {
|
||||
block::PublicKey::parse("pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2").ensure_error();
|
||||
auto key = block::PublicKey::parse("Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2").move_as_ok();
|
||||
CHECK(td::buffer_to_hex(key.key) == "3EE9DC0A7A0B6CA01770CE34698792BD8ECB53A6949BFD6C81B6E3CA475B74D7");
|
||||
CHECK(key.serialize() == "Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2");
|
||||
}
|
||||
|
||||
TEST(Tonlib, Address) {
|
||||
auto a = block::StdAddress::parse("-1:538fa7cc24ff8eaa101d84a5f1ab7e832fe1d84b309cdfef4ee94373aac80f7d").move_as_ok();
|
||||
|
@ -287,12 +293,14 @@ TEST(Tonlib, KeysApi) {
|
|||
auto local_password = td::SecureString("local password");
|
||||
auto mnemonic_password = td::SecureString("mnemonic password");
|
||||
{
|
||||
auto key = sync_send(client, make_object<tonlib_api::createNewKey>(local_password.copy(), td::SecureString{}))
|
||||
auto key = sync_send(client, make_object<tonlib_api::createNewKey>(local_password.copy(), td::SecureString{},
|
||||
td::SecureString{}))
|
||||
.move_as_ok();
|
||||
}
|
||||
|
||||
//createNewKey local_password:bytes mnemonic_password:bytes = Key;
|
||||
auto key = sync_send(client, make_object<tonlib_api::createNewKey>(local_password.copy(), mnemonic_password.copy()))
|
||||
auto key = sync_send(client, make_object<tonlib_api::createNewKey>(local_password.copy(), mnemonic_password.copy(),
|
||||
td::SecureString{}))
|
||||
.move_as_ok();
|
||||
|
||||
sync_send(client, make_object<tonlib_api::exportKey>(make_object<tonlib_api::inputKey>(
|
||||
|
|
|
@ -126,9 +126,9 @@ void transfer_grams(Client& client, std::string from, std::string to, td::int64
|
|||
}
|
||||
Wallet create_empty_wallet(Client& client) {
|
||||
using tonlib_api::make_object;
|
||||
auto key =
|
||||
sync_send(client, make_object<tonlib_api::createNewKey>(td::SecureString("local"), td::SecureString("mnemonic")))
|
||||
.move_as_ok();
|
||||
auto key = sync_send(client, make_object<tonlib_api::createNewKey>(td::SecureString("local"),
|
||||
td::SecureString("mnemonic"), td::SecureString()))
|
||||
.move_as_ok();
|
||||
Wallet wallet{"", {key->public_key_, std::move(key->secret_)}};
|
||||
|
||||
auto account_address =
|
||||
|
@ -210,8 +210,8 @@ int main(int argc, char* argv[]) {
|
|||
// init
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(global_config_str, "."))).ensure();
|
||||
|
||||
auto key = sync_send(client,
|
||||
make_object<tonlib_api::createNewKey>(td::SecureString("local"), td::SecureString("mnemonic")))
|
||||
auto key = sync_send(client, make_object<tonlib_api::createNewKey>(
|
||||
td::SecureString("local"), td::SecureString("mnemonic"), td::SecureString()))
|
||||
.move_as_ok();
|
||||
|
||||
auto create_input_key = [&] {
|
||||
|
|
|
@ -63,9 +63,11 @@ td::Result<KeyStorage::Key> KeyStorage::save_key(const DecryptedKey &decrypted_k
|
|||
return std::move(res);
|
||||
}
|
||||
|
||||
td::Result<KeyStorage::Key> KeyStorage::create_new_key(td::Slice local_password, td::Slice mnemonic_password) {
|
||||
td::Result<KeyStorage::Key> KeyStorage::create_new_key(td::Slice local_password, td::Slice mnemonic_password,
|
||||
td::Slice entropy) {
|
||||
Mnemonic::Options create_options;
|
||||
create_options.password = td::SecureString(mnemonic_password);
|
||||
create_options.entropy = td::SecureString(entropy);
|
||||
TRY_RESULT(mnemonic, Mnemonic::create_new(std::move(create_options)));
|
||||
|
||||
return save_key(DecryptedKey(std::move(mnemonic)), local_password);
|
||||
|
|
|
@ -50,7 +50,7 @@ class KeyStorage {
|
|||
|
||||
td::Status set_directory(std::string directory);
|
||||
|
||||
td::Result<Key> create_new_key(td::Slice local_password, td::Slice key_password);
|
||||
td::Result<Key> create_new_key(td::Slice local_password, td::Slice key_password, td::Slice entropy);
|
||||
|
||||
td::Result<ExportedKey> export_key(InputKey input_key);
|
||||
td::Result<ExportedPemKey> export_pem_key(InputKey input_key, td::Slice key_password);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "tonlib/TestWallet.h"
|
||||
#include "tonlib/TestGiver.h"
|
||||
#include "tonlib/utils.h"
|
||||
#include "tonlib/keys/Mnemonic.h"
|
||||
|
||||
#include "auto/tl/tonlib_api.hpp"
|
||||
#include "block/block-auto.h"
|
||||
|
@ -350,6 +351,7 @@ bool TonlibClient::is_static_request(td::int32 id) {
|
|||
case tonlib_api::raw_getAccountAddress::ID:
|
||||
case tonlib_api::testWallet_getAccountAddress::ID:
|
||||
case tonlib_api::testGiver_getAccountAddress::ID:
|
||||
case tonlib_api::getBip39Hints::ID:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -405,6 +407,11 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
|
|||
return tonlib_api::make_object<tonlib_api::accountAddress>(TestGiver::address().rserialize());
|
||||
}
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(tonlib_api::getBip39Hints& request) {
|
||||
return tonlib_api::make_object<tonlib_api::bip39Hints>(
|
||||
td::transform(Mnemonic::word_hints(td::trim(td::to_lower_inplace(request.prefix_))), [](auto& x) { return x; }));
|
||||
}
|
||||
|
||||
td::Status TonlibClient::do_request(const tonlib_api::init& request,
|
||||
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
|
||||
if (state_ != State::Uninited) {
|
||||
|
@ -900,8 +907,8 @@ td::Status TonlibClient::do_request(tonlib_api::generic_sendGrams& request,
|
|||
|
||||
td::Status TonlibClient::do_request(const tonlib_api::createNewKey& request,
|
||||
td::Promise<object_ptr<tonlib_api::key>>&& promise) {
|
||||
TRY_RESULT(key,
|
||||
key_storage_.create_new_key(std::move(request.local_password_), std::move(request.mnemonic_password_)));
|
||||
TRY_RESULT(key, key_storage_.create_new_key(std::move(request.local_password_), std::move(request.mnemonic_password_),
|
||||
std::move(request.random_extra_seed_)));
|
||||
promise.set_value(tonlib_api::make_object<tonlib_api::key>(key.public_key.as_slice().str(), std::move(key.secret)));
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ class TonlibClient : public td::actor::Actor {
|
|||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::raw_getAccountAddress& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::testWallet_getAccountAddress& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::testGiver_getAccountAddress& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(tonlib_api::getBip39Hints& request);
|
||||
template <class T, class P>
|
||||
td::Status do_request(const T& request, P&& promise) {
|
||||
return td::Status::Error(400, "Function is unsupported");
|
||||
|
|
|
@ -28,9 +28,12 @@
|
|||
#include "td/utils/Span.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/optional.h"
|
||||
#include "td/utils/Timer.h"
|
||||
|
||||
#include "crypto/Ed25519.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tonlib {
|
||||
td::Result<Mnemonic> Mnemonic::create(td::SecureString words, td::SecureString password) {
|
||||
return create_from_normalized(normalize_and_split(std::move(words)), std::move(password));
|
||||
|
@ -133,7 +136,28 @@ td::SecureString Mnemonic::join(td::Span<td::SecureString> words) {
|
|||
return res;
|
||||
}
|
||||
|
||||
td::Span<std::string> Mnemonic::word_hints(td::Slice prefix) {
|
||||
static std::vector<std::string> words = [] {
|
||||
auto bip_words = Mnemonic::normalize_and_split(td::SecureString(bip39_english()));
|
||||
std::vector<std::string> res;
|
||||
for (auto &word : bip_words) {
|
||||
res.push_back(word.as_slice().str());
|
||||
}
|
||||
return res;
|
||||
}();
|
||||
if (prefix.empty()) {
|
||||
return words;
|
||||
}
|
||||
|
||||
auto p = std::equal_range(words.begin(), words.end(), prefix, [&](td::Slice a, td::Slice b) {
|
||||
return a.truncate(prefix.size()) < b.truncate(prefix.size());
|
||||
});
|
||||
|
||||
return td::Span<std::string>(&*p.first, p.second - p.first);
|
||||
}
|
||||
|
||||
td::Result<Mnemonic> Mnemonic::create_new(Options options) {
|
||||
td::Timer timer;
|
||||
if (options.words_count == 0) {
|
||||
options.words_count = 24;
|
||||
}
|
||||
|
@ -146,14 +170,28 @@ td::Result<Mnemonic> Mnemonic::create_new(Options options) {
|
|||
max_iterations *= 256;
|
||||
}
|
||||
|
||||
td::Random::add_seed(options.entropy.as_slice());
|
||||
SCOPE_EXIT {
|
||||
td::Random::secure_cleanup();
|
||||
};
|
||||
|
||||
auto bip_words = Mnemonic::normalize_and_split(td::SecureString(bip39_english()));
|
||||
CHECK(bip_words.size() == 2048);
|
||||
|
||||
int A = 0, B = 0, C = 0;
|
||||
for (int iteration = 0; iteration < max_iterations; iteration++) {
|
||||
std::vector<td::SecureString> words;
|
||||
td::SecureString rnd((options.words_count * 11 + 7) / 8);
|
||||
td::Random::secure_bytes(rnd.as_mutable_slice());
|
||||
for (int i = 0; i < options.words_count; i++) {
|
||||
words.push_back(bip_words[td::Random::secure_int32() & 2047].copy());
|
||||
size_t word_i = 0;
|
||||
for (size_t j = 0; j < 11; j++) {
|
||||
size_t offset = i * 11 + j;
|
||||
if ((rnd[offset / 8] & (1 << (offset & 7))) != 0) {
|
||||
word_i |= 1 << j;
|
||||
}
|
||||
}
|
||||
words.push_back(bip_words[word_i].copy());
|
||||
}
|
||||
|
||||
bool has_password = !options.password.empty();
|
||||
|
@ -180,7 +218,7 @@ td::Result<Mnemonic> Mnemonic::create_new(Options options) {
|
|||
continue;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Mnemonic generation debug stats: " << A << " " << B << " " << C;
|
||||
LOG(INFO) << "Mnemonic generation debug stats: " << A << " " << B << " " << C << " " << timer;
|
||||
return std::move(mnemonic);
|
||||
}
|
||||
return td::Status::Error("Failed to create a mnemonic (should not happen)");
|
||||
|
|
|
@ -36,6 +36,7 @@ class Mnemonic {
|
|||
}
|
||||
int words_count = 24;
|
||||
td::SecureString password;
|
||||
td::SecureString entropy;
|
||||
};
|
||||
static td::Result<Mnemonic> create_new(Options options = {});
|
||||
|
||||
|
@ -51,6 +52,7 @@ class Mnemonic {
|
|||
std::vector<td::SecureString> get_words() const;
|
||||
|
||||
static std::vector<td::SecureString> normalize_and_split(td::SecureString words);
|
||||
static td::Span<std::string> word_hints(td::Slice prefix);
|
||||
|
||||
private:
|
||||
std::vector<td::SecureString> words_;
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Span.h"
|
||||
|
||||
namespace tonlib {
|
||||
td::CSlice bip39_english();
|
||||
}
|
||||
} // namespace tonlib
|
||||
|
|
|
@ -152,6 +152,8 @@ class TonlibCli : public td::actor::Actor {
|
|||
auto to = parser.read_word();
|
||||
auto grams = parser.read_word();
|
||||
transfer(from, to, grams);
|
||||
} else if (cmd == "hint") {
|
||||
get_hints(parser.read_word());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,21 +193,27 @@ class TonlibCli : public td::actor::Actor {
|
|||
};
|
||||
}
|
||||
|
||||
void generate_key(std::string entropy = "") {
|
||||
void generate_key(td::SecureString entropy = {}) {
|
||||
if (entropy.size() < 20) {
|
||||
td::TerminalIO::out() << "Enter some entropy";
|
||||
cont_ = [this, entropy](td::Slice new_entropy) { generate_key(entropy + new_entropy.str()); };
|
||||
cont_ = [this, entropy = std::move(entropy)](td::Slice new_entropy) {
|
||||
td::SecureString res(entropy.size() + new_entropy.size());
|
||||
res.as_mutable_slice().copy_from(entropy.as_slice());
|
||||
res.as_mutable_slice().substr(entropy.size()).copy_from(new_entropy);
|
||||
generate_key(std::move(res));
|
||||
};
|
||||
return;
|
||||
}
|
||||
td::TerminalIO::out() << "Enter password (could be empty)";
|
||||
cont_ = [this, entropy](td::Slice password) { generate_key(std::move(entropy), td::SecureString(password)); };
|
||||
cont_ = [this, entropy = std::move(entropy)](td::Slice password) mutable {
|
||||
generate_key(std::move(entropy), td::SecureString(password));
|
||||
};
|
||||
}
|
||||
|
||||
void generate_key(std::string entropy, td::SecureString password) {
|
||||
//TODO: use entropy
|
||||
void generate_key(td::SecureString entropy, td::SecureString password) {
|
||||
auto password_copy = password.copy();
|
||||
send_query(tonlib_api::make_object<tonlib_api::createNewKey>(std::move(password_copy),
|
||||
td::SecureString() /*mnemonic password*/),
|
||||
send_query(tonlib_api::make_object<tonlib_api::createNewKey>(
|
||||
std::move(password_copy), td::SecureString() /*mnemonic password*/, std::move(entropy)),
|
||||
[this, password = std::move(password)](auto r_key) mutable {
|
||||
if (r_key.is_error()) {
|
||||
LOG(ERROR) << "Failed to create new key: " << r_key.error();
|
||||
|
@ -542,6 +550,15 @@ class TonlibCli : public td::actor::Actor {
|
|||
td::TerminalIO::out() << to_string(r_res.ok());
|
||||
});
|
||||
}
|
||||
|
||||
void get_hints(td::Slice prefix) {
|
||||
using tonlib_api::make_object;
|
||||
auto obj = tonlib::TonlibClient::static_request(make_object<tonlib_api::getBip39Hints>(prefix.str()));
|
||||
if (obj->get_id() == tonlib_api::error::ID) {
|
||||
return;
|
||||
}
|
||||
td::TerminalIO::out() << to_string(obj);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue