1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-15 04:32:21 +00:00
ton/tonlib/tonlib/LastConfig.cpp
EmelyanenkoK 6074702d05
Fix extracting version from config in tonlib (#748)
Co-authored-by: SpyCheese <mikle98@yandex.ru>
2023-07-17 17:20:01 +03:00

154 lines
5 KiB
C++

/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2020 Telegram Systems LLP
*/
#include "tonlib/LastConfig.h"
#include "tonlib/utils.h"
#include "ton/lite-tl.hpp"
#include "block/check-proof.h"
#include "block/mc-config.h"
#include "block/block-auto.h"
#include "lite-client/lite-client-common.h"
#include "LastBlock.h"
namespace tonlib {
// init_state <-> last_key_block
// state.valitated_init_state
// last_key_block ->
//
td::StringBuilder& operator<<(td::StringBuilder& sb, const LastConfigState& state) {
return sb;
}
LastConfig::LastConfig(ExtClientRef client, td::unique_ptr<Callback> callback) : callback_(std::move(callback)) {
client_.set_client(client);
VLOG(last_block) << "State: " << state_;
}
void LastConfig::get_last_config(td::Promise<LastConfigState> promise) {
if (promises_.empty() && get_config_state_ == QueryState::Done) {
VLOG(last_config) << "start";
VLOG(last_config) << "get_config: reset";
get_config_state_ = QueryState::Empty;
}
promises_.push_back(std::move(promise));
loop();
}
void LastConfig::with_last_block(td::Result<LastBlockState> r_last_block) {
if (r_last_block.is_error()) {
on_error(r_last_block.move_as_error());
return;
}
auto last_block = r_last_block.move_as_ok();
client_.send_query(ton::lite_api::liteServer_getConfigAll(block::ConfigInfo::needPrevBlocks,
create_tl_lite_block_id(last_block.last_block_id)),
[this](auto r_config) { this->on_config(std::move(r_config)); });
}
void LastConfig::on_config(td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_configInfo>> r_config) {
auto status = process_config(std::move(r_config));
if (status.is_ok()) {
on_ok();
get_config_state_ = QueryState::Done;
} else {
on_error(std::move(status));
get_config_state_ = QueryState::Empty;
}
}
td::Status LastConfig::process_config(
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_configInfo>> r_config) {
TRY_RESULT(raw_config, std::move(r_config));
TRY_STATUS_PREFIX(TRY_VM(process_config_proof(std::move(raw_config))), TonlibError::ValidateConfig());
return td::Status::OK();
}
td::Status LastConfig::process_config_proof(ton::ton_api::object_ptr<ton::lite_api::liteServer_configInfo> raw_config) {
auto blkid = create_block_id(raw_config->id_);
if (!blkid.is_masterchain_ext()) {
return td::Status::Error(PSLICE() << "reference block " << blkid.to_str()
<< " for the configuration is not a valid masterchain block");
}
TRY_RESULT(state, block::check_extract_state_proof(blkid, raw_config->state_proof_.as_slice(),
raw_config->config_proof_.as_slice()));
TRY_RESULT(config, block::ConfigInfo::extract_config(
std::move(state), block::ConfigInfo::needPrevBlocks | block::ConfigInfo::needCapabilities));
for (auto i : params_) {
VLOG(last_config) << "ConfigParam(" << i << ") = ";
auto value = config->get_config_param(i);
if (value.is_null()) {
VLOG(last_config) << "(null)\n";
} else {
std::ostringstream os;
if (i >= 0) {
block::gen::ConfigParam{i}.print_ref(os, value);
os << std::endl;
}
vm::load_cell_slice(value).print_rec(os);
VLOG(last_config) << os.str();
}
}
TRY_RESULT_ASSIGN(state_.prev_blocks_info, config->get_prev_blocks_info());
state_.config.reset(config.release());
return td::Status::OK();
}
void LastConfig::loop() {
if (promises_.empty()) {
return;
}
if (get_config_state_ == QueryState::Empty) {
VLOG(last_block) << "get_config: start";
get_config_state_ = QueryState::Active;
client_.with_last_block(
[self = this](td::Result<LastBlockState> r_last_block) { self->with_last_block(std::move(r_last_block)); });
}
}
void LastConfig::on_ok() {
VLOG(last_block) << "ok " << state_;
for (auto& promise : promises_) {
auto state = state_;
promise.set_value(std::move(state));
}
promises_.clear();
}
void LastConfig::on_error(td::Status status) {
VLOG(last_config) << "error " << status;
for (auto& promise : promises_) {
promise.set_error(status.clone());
}
promises_.clear();
get_config_state_ = QueryState::Empty;
}
void LastConfig::tear_down() {
on_error(TonlibError::Cancelled());
}
} // namespace tonlib