1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

updated block header

1. Updated block header, proofs now contain more data
   Notice, that old proofs may become invalid in the future
2. Fixed message routing
3. Fixed block creator id in block header
4. Support for full proofs in tonlib
5. Support for partial state download
6. Some other bugfixes
This commit is contained in:
ton 2019-09-18 21:46:32 +04:00
parent bce33f588a
commit 13140ddf29
73 changed files with 2084 additions and 304 deletions

View file

@ -50,9 +50,9 @@ add_library(tonlib STATIC ${TONLIB_SOURCE})
target_include_directories(tonlib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/..
${OPENSSL_INCLUDE_DIR}
$<BUILD_INTERFACE:${OPENSSL_INCLUDE_DIR}>
)
target_link_libraries(tonlib PRIVATE tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ton_block)
target_link_libraries(tonlib PRIVATE tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ton_block lite-client-common)
target_link_libraries(tonlib PUBLIC tdutils tl_tonlib_api)
if (TONLIB_ENABLE_JNI AND NOT ANDROID) # jni is available by default on Android
@ -119,7 +119,8 @@ install(TARGETS tonlibjson TonlibJson EXPORT Tonlib
)
if (NOT TON_USE_ABSEIL)
install(TARGETS tdnet keys crc32c tdactor adnllite tl_api tl-utils tl_lite_api tl-lite-utils ton_crypto ton_block tdutils tl_tonlib_api tonlib Tonlib EXPORT Tonlib
install(TARGETS tdnet keys crc32c tdactor adnllite tl_api tl-utils tl_lite_api tl-lite-utils ton_crypto ton_block
tdutils tl_tonlib_api tonlib lite-client-common Tonlib EXPORT Tonlib
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin

View file

@ -65,6 +65,55 @@ td::Result<Config> Config::parse(std::string str) {
client.adnl_id = ton::adnl::AdnlNodeIdFull(ton::pubkeys::Ed25519(td::Bits256(td::Slice(key).ubegin())));
res.lite_clients.push_back(std::move(client));
}
TRY_RESULT(validator_obj,
td::get_json_object_field(json.get_object(), "validator", td::JsonValue::Type::Object, false));
auto &validator = validator_obj.get_object();
TRY_RESULT(validator_type, td::get_json_object_string_field(validator, "@type", false));
if (validator_type != "validator.config.global") {
return td::Status::Error("Invalid config (7)");
}
TRY_RESULT(zero_state_obj, td::get_json_object_field(validator, "zero_state", td::JsonValue::Type::Object, false));
auto &zero_state = zero_state_obj.get_object();
ton::WorkchainId zero_workchain_id;
{
TRY_RESULT(wc, td::get_json_object_int_field(zero_state, "workchain"));
zero_workchain_id = wc;
}
ton::ShardId zero_shard_id; // uint64
{
TRY_RESULT(shard_id, td::get_json_object_long_field(zero_state, "shard"));
zero_shard_id = static_cast<ton::ShardId>(shard_id);
}
ton::BlockSeqno zero_seqno;
{
TRY_RESULT(seqno, td::get_json_object_int_field(zero_state, "seqno"));
zero_seqno = seqno;
}
ton::RootHash zero_root_hash;
{
TRY_RESULT(hash_b64, td::get_json_object_string_field(zero_state, "root_hash"));
TRY_RESULT(hash, td::base64_decode(hash_b64));
if (hash.size() * 8 != ton::RootHash::size()) {
return td::Status::Error("Invalid config (8)");
}
zero_root_hash = ton::RootHash(td::ConstBitPtr(td::Slice(hash).ubegin()));
}
ton::FileHash zero_file_hash;
{
TRY_RESULT(hash_b64, td::get_json_object_string_field(zero_state, "file_hash"));
TRY_RESULT(hash, td::base64_decode(hash_b64));
if (hash.size() * 8 != ton::FileHash::size()) {
return td::Status::Error("Invalid config (9)");
}
zero_file_hash = ton::RootHash(td::ConstBitPtr(td::Slice(hash).ubegin()));
}
res.zero_state_id = ton::BlockIdExt(zero_workchain_id, zero_shard_id, zero_seqno, std::move(zero_root_hash),
std::move(zero_file_hash));
return res;
}
} // namespace tonlib

View file

@ -19,6 +19,7 @@
#pragma once
#include "adnl/adnl-node-id.hpp"
#include "td/utils/port/IPAddress.h"
#include "ton/ton-types.h"
namespace tonlib {
struct Config {
@ -26,6 +27,7 @@ struct Config {
ton::adnl::AdnlNodeIdFull adnl_id;
td::IPAddress address;
};
ton::BlockIdExt zero_state_id;
std::vector<LiteClient> lite_clients;
static td::Result<Config> parse(std::string str);
};

View file

@ -20,8 +20,13 @@
#include "ton/lite-tl.hpp"
#include "lite-client/lite-client-common.h"
namespace tonlib {
LastBlock::LastBlock(ExtClientRef client, td::actor::ActorShared<> parent) {
LastBlock::LastBlock(ExtClientRef client, ton::ZeroStateIdExt zero_state_id, ton::BlockIdExt last_block_id,
td::actor::ActorShared<> parent) {
zero_state_id_ = std::move(zero_state_id);
mc_last_block_id_ = std::move(last_block_id);
client_.set_client(client);
parent_ = std::move(parent);
}
@ -36,7 +41,48 @@ void LastBlock::get_last_block(td::Promise<ton::BlockIdExt> promise) {
void LastBlock::do_get_last_block() {
client_.send_query(ton::lite_api::liteServer_getMasterchainInfo(),
[this](auto r_info) { this->on_masterchain_info(std::move(r_info)); });
return;
//liteServer.getBlockProof mode:# known_block:tonNode.blockIdExt target_block:mode.0?tonNode.blockIdExt = liteServer.PartialBlockProof;
client_.send_query(
ton::lite_api::liteServer_getBlockProof(0, create_tl_lite_block_id(mc_last_block_id_), nullptr),
[this, from = mc_last_block_id_](auto r_block_proof) { this->on_block_proof(from, std::move(r_block_proof)); });
}
td::Result<bool> LastBlock::process_block_proof(
ton::BlockIdExt from,
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof>> r_block_proof) {
TRY_RESULT(block_proof, std::move(r_block_proof));
LOG(ERROR) << to_string(block_proof);
TRY_RESULT(chain, liteclient::deserialize_proof_chain(std::move(block_proof)));
if (chain->from != from) {
return td::Status::Error(PSLICE() << "block proof chain starts from block " << chain->from.to_str()
<< ", not from requested block " << from.to_str());
}
TRY_STATUS(chain->validate());
update_mc_last_block(chain->to);
return chain->complete;
}
void LastBlock::on_block_proof(
ton::BlockIdExt from,
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof>> r_block_proof) {
auto r_is_ready = process_block_proof(from, std::move(r_block_proof));
if (r_is_ready.is_error()) {
LOG(WARNING) << "Failed liteServer_getBlockProof " << r_block_proof.error();
return;
}
auto is_ready = r_is_ready.move_as_ok();
if (is_ready) {
for (auto& promise : promises_) {
auto copy = mc_last_block_id_;
promise.set_value(std::move(copy));
}
promises_.clear();
} else {
do_get_last_block();
}
}
void LastBlock::on_masterchain_info(
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_masterchainInfo>> r_info) {
if (r_info.is_ok()) {

View file

@ -24,7 +24,8 @@
namespace tonlib {
class LastBlock : public td::actor::Actor {
public:
explicit LastBlock(ExtClientRef client, td::actor::ActorShared<> parent);
explicit LastBlock(ExtClientRef client, ton::ZeroStateIdExt zero_state_id, ton::BlockIdExt last_block_id,
td::actor::ActorShared<> parent);
void get_last_block(td::Promise<ton::BlockIdExt> promise);
@ -39,6 +40,11 @@ class LastBlock : public td::actor::Actor {
void do_get_last_block();
void on_masterchain_info(td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_masterchainInfo>> r_info);
void on_block_proof(ton::BlockIdExt from,
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof>> r_block_proof);
td::Result<bool> process_block_proof(
ton::BlockIdExt from,
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof>> r_block_proof);
void update_zero_state(ton::ZeroStateIdExt zero_state_id);

View file

@ -280,7 +280,11 @@ void TonlibClient::init_ext_client() {
raw_client_ = ExtClientLazy::create(lite_client.adnl_id, lite_client.address,
td::make_unique<Callback>(td::actor::actor_shared()));
ref_cnt_++;
raw_last_block_ = td::actor::create_actor<LastBlock>("LastBlock", get_client_ref(), td::actor::actor_shared());
raw_last_block_ = td::actor::create_actor<LastBlock>(
"LastBlock", get_client_ref(),
ton::ZeroStateIdExt(config_.zero_state_id.id.workchain, config_.zero_state_id.root_hash,
config_.zero_state_id.file_hash),
config_.zero_state_id, td::actor::actor_shared());
client_.set_client(get_client_ref());
}
@ -382,7 +386,8 @@ td::Result<block::StdAddress> get_account_address(const tonlib_api::raw_initialA
}
td::Result<block::StdAddress> get_account_address(const tonlib_api::testWallet_initialAccountState& test_wallet_state) {
auto key = td::Ed25519::PublicKey(td::SecureString(test_wallet_state.public_key_));
TRY_RESULT(key_bytes, block::PublicKey::parse(test_wallet_state.public_key_));
auto key = td::Ed25519::PublicKey(td::SecureString(key_bytes.key));
return GenericAccount::get_address(0 /*zerochain*/, TestWallet::get_init_state(key));
}
@ -733,7 +738,8 @@ td::Result<KeyStorage::InputKey> from_tonlib(tonlib_api::inputKey& input_key) {
return td::Status::Error(400, "Field key must not be empty");
}
return KeyStorage::InputKey{{td::SecureString(input_key.key_->public_key_), std::move(input_key.key_->secret_)},
TRY_RESULT(key_bytes, block::PublicKey::parse(input_key.key_->public_key_));
return KeyStorage::InputKey{{td::SecureString(key_bytes.key), std::move(input_key.key_->secret_)},
std::move(input_key.local_password_)};
}
@ -909,7 +915,8 @@ 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_),
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)));
TRY_RESULT(key_bytes, block::PublicKey::from_bytes(key.public_key.as_slice()));
promise.set_value(tonlib_api::make_object<tonlib_api::key>(key_bytes.serialize(), std::move(key.secret)));
return td::Status::OK();
}
@ -926,7 +933,8 @@ td::Status TonlibClient::do_request(const tonlib_api::exportKey& request,
td::Status TonlibClient::do_request(const tonlib_api::deleteKey& request,
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
TRY_STATUS(key_storage_.delete_key(request.public_key_));
TRY_RESULT(key_bytes, block::PublicKey::parse(request.public_key_));
TRY_STATUS(key_storage_.delete_key(key_bytes.key));
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
return td::Status::OK();
}
@ -938,7 +946,8 @@ td::Status TonlibClient::do_request(const tonlib_api::importKey& request,
}
TRY_RESULT(key, key_storage_.import_key(std::move(request.local_password_), std::move(request.mnemonic_password_),
KeyStorage::ExportedKey{std::move(request.exported_key_->word_list_)}));
promise.set_value(tonlib_api::make_object<tonlib_api::key>(key.public_key.as_slice().str(), std::move(key.secret)));
TRY_RESULT(key_bytes, block::PublicKey::from_bytes(key.public_key.as_slice()));
promise.set_value(tonlib_api::make_object<tonlib_api::key>(key_bytes.serialize(), std::move(key.secret)));
return td::Status::OK();
}
@ -951,9 +960,9 @@ td::Status TonlibClient::do_request(const tonlib_api::exportPemKey& request,
return td::Status::Error(400, "Field key must not be empty");
}
KeyStorage::InputKey input_key{
{td::SecureString(request.input_key_->key_->public_key_), std::move(request.input_key_->key_->secret_)},
std::move(request.input_key_->local_password_)};
TRY_RESULT(key_bytes, block::PublicKey::parse(request.input_key_->key_->public_key_));
KeyStorage::InputKey input_key{{td::SecureString(key_bytes.key), std::move(request.input_key_->key_->secret_)},
std::move(request.input_key_->local_password_)};
TRY_RESULT(exported_pem_key, key_storage_.export_pem_key(std::move(input_key), std::move(request.key_password_)));
promise.set_value(tonlib_api::make_object<tonlib_api::exportedPemKey>(std::move(exported_pem_key.pem)));
return td::Status::OK();
@ -966,7 +975,8 @@ td::Status TonlibClient::do_request(const tonlib_api::importPemKey& request,
}
TRY_RESULT(key, key_storage_.import_pem_key(std::move(request.local_password_), std::move(request.key_password_),
KeyStorage::ExportedPemKey{std::move(request.exported_key_->pem_)}));
promise.set_value(tonlib_api::make_object<tonlib_api::key>(key.public_key.as_slice().str(), std::move(key.secret)));
TRY_RESULT(key_bytes, block::PublicKey::from_bytes(key.public_key.as_slice()));
promise.set_value(tonlib_api::make_object<tonlib_api::key>(key_bytes.serialize(), std::move(key.secret)));
return td::Status::OK();
}
@ -989,7 +999,8 @@ td::Status TonlibClient::do_request(const tonlib_api::importEncryptedKey& reques
TRY_RESULT(key, key_storage_.import_encrypted_key(
std::move(request.local_password_), std::move(request.key_password_),
KeyStorage::ExportedEncryptedKey{std::move(request.exported_encrypted_key_->data_)}));
promise.set_value(tonlib_api::make_object<tonlib_api::key>(key.public_key.as_slice().str(), std::move(key.secret)));
TRY_RESULT(key_bytes, block::PublicKey::from_bytes(key.public_key.as_slice()));
promise.set_value(tonlib_api::make_object<tonlib_api::key>(key_bytes.serialize(), std::move(key.secret)));
return td::Status::OK();
}
@ -1001,11 +1012,10 @@ td::Status TonlibClient::do_request(const tonlib_api::changeLocalPassword& reque
if (!request.input_key_->key_) {
return td::Status::Error(400, "Field key must not be empty");
}
KeyStorage::InputKey input_key{
{td::SecureString(request.input_key_->key_->public_key_), std::move(request.input_key_->key_->secret_)},
std::move(request.input_key_->local_password_)};
TRY_RESULT(input_key, from_tonlib(*request.input_key_));
TRY_RESULT(key, key_storage_.change_local_password(std::move(input_key), std::move(request.new_local_password_)));
promise.set_value(tonlib_api::make_object<tonlib_api::key>(key.public_key.as_slice().str(), std::move(key.secret)));
promise.set_value(
tonlib_api::make_object<tonlib_api::key>(request.input_key_->key_->public_key_, std::move(key.secret)));
return td::Status::OK();
}

View file

@ -233,7 +233,7 @@ class TonlibCli : public td::actor::Actor {
td::SecureString buf(10000);
td::StringBuilder sb(buf.as_mutable_slice());
for (auto& info : keys_) {
sb << td::base64_encode(info.public_key) << " " << td::base64_encode(info.secret) << "\n";
sb << info.public_key << " " << td::base64_encode(info.secret) << "\n";
}
LOG_IF(FATAL, sb.is_error()) << "StringBuilder overflow";
td::atomic_write_file(key_db_path(), sb.as_cslice());
@ -247,21 +247,20 @@ class TonlibCli : public td::actor::Actor {
auto db = r_db.move_as_ok();
td::ConstParser parser(db.as_slice());
while (true) {
auto public_key_b64 = parser.read_word();
auto public_key = parser.read_word();
auto secret_b64 = parser.read_word();
if (secret_b64.empty()) {
break;
}
auto r_public_key = td::base64_decode(public_key_b64);
auto r_secret = td::base64_decode_secure(secret_b64);
if (r_public_key.is_error() || r_secret.is_error()) {
LOG(ERROR) << "Invalid key database at " << key_db_path();
if (r_secret.is_error()) {
LOG(ERROR) << "Invalid secret database at " << key_db_path();
}
KeyInfo info;
info.public_key = r_public_key.move_as_ok();
info.public_key = public_key.str();
info.secret = r_secret.move_as_ok();
LOG(INFO) << td::buffer_to_hex(info.public_key);
LOG(INFO) << info.public_key;
keys_.push_back(std::move(info));
}
@ -271,7 +270,7 @@ class TonlibCli : public td::actor::Actor {
td::TerminalIO::out() << "Got " << keys_.size() << " keys"
<< "\n";
for (size_t i = 0; i < keys_.size(); i++) {
td::TerminalIO::out() << " #" << i << ": " << td::buffer_to_hex(keys_[i].public_key) << "\n";
td::TerminalIO::out() << " #" << i << ": " << keys_[i].public_key << "\n";
}
}
@ -302,7 +301,7 @@ class TonlibCli : public td::actor::Actor {
size_t res = 0;
size_t cnt = 0;
for (size_t i = 0; i < keys_.size(); i++) {
auto full_key = td::to_lower(td::buffer_to_hex(keys_[i].public_key));
auto full_key = td::to_lower(keys_[i].public_key);
if (td::begins_with(full_key, prefix)) {
res = i;
cnt++;
@ -452,27 +451,22 @@ class TonlibCli : public td::actor::Actor {
cont_ = [this](td::Slice key) { this->get_state(key); };
return;
}
auto r_key_i = to_key_i(key);
if (r_key_i.is_error()) {
auto r_address = to_account_address(key, false);
if (r_address.is_error()) {
td::TerminalIO::out() << "Unknown key id: [" << key << "]\n";
return;
}
auto key_i = r_key_i.move_as_ok();
auto address = r_address.move_as_ok();
using tonlib_api::make_object;
auto obj = tonlib::TonlibClient::static_request(make_object<tonlib_api::testWallet_getAccountAddress>(
make_object<tonlib_api::testWallet_initialAccountState>(keys_[key_i].public_key)));
if (obj->get_id() == tonlib_api::error::ID) {
td::TerminalIO::out() << "Can't get state of [" << key << "] : " << to_string(obj);
}
send_query(
make_object<tonlib_api::generic_getAccountState>(ton::move_tl_object_as<tonlib_api::accountAddress>(obj)),
[](auto r_res) {
if (r_res.is_error()) {
td::TerminalIO::out() << "Can't get state: " << r_res.error() << "\n";
return;
}
td::TerminalIO::out() << to_string(r_res.ok());
});
send_query(make_object<tonlib_api::generic_getAccountState>(
ton::move_tl_object_as<tonlib_api::accountAddress>(std::move(address.address))),
[](auto r_res) {
if (r_res.is_error()) {
td::TerminalIO::out() << "Can't get state: " << r_res.error() << "\n";
return;
}
td::TerminalIO::out() << to_string(r_res.ok());
});
}
void transfer(td::Slice from, td::Slice to, td::Slice grams) {
@ -497,6 +491,7 @@ class TonlibCli : public td::actor::Actor {
td::Slice password) mutable { this->transfer(std::move(from), std::move(to), grams, password); };
return;
}
transfer(r_from_address.move_as_ok(), r_to_address.move_as_ok(), r_grams.move_as_ok(), "");
}
void transfer(Address from, Address to, td::uint64 grams, td::Slice password) {