1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-15 04:32:21 +00:00
ton/tonlib/tonlib/LastBlock.h
ton 9f008b129f updated submodules, bugfixes
- added new fift/func code for validator complaint creation
- bugfixes in validator
- updates in tonlib
- new versions of rocksdb/abseil
- hardfork support
2020-04-27 16:01:46 +04:00

246 lines
7.7 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
*/
#pragma once
#include "td/actor/actor.h"
#include "tonlib/Config.h"
#include "tonlib/ExtClient.h"
#include "td/utils/CancellationToken.h"
#include "td/utils/tl_helpers.h"
namespace block {
struct BlockProofChain;
}
namespace tonlib {
td::StringBuilder &operator<<(td::StringBuilder &sb, const LastBlockState &state);
template <unsigned int N, class StorerT>
void store(const td::BitArray<N> &arr, StorerT &storer) {
storer.store_binary(arr);
}
template <unsigned int N, class ParserT>
void parse(td::BitArray<N> &arr, ParserT &parser) {
arr = parser.template fetch_binary<td::BitArray<N>>();
}
template <class StorerT>
void store(const ton::ZeroStateIdExt &zero_state_id, StorerT &storer) {
using td::store;
using tonlib::store;
store(zero_state_id.workchain, storer);
store(zero_state_id.root_hash, storer);
store(zero_state_id.file_hash, storer);
}
template <class ParserT>
void parse(ton::ZeroStateIdExt &zero_state_id, ParserT &parser) {
using td::parse;
using tonlib::parse;
parse(zero_state_id.workchain, parser);
parse(zero_state_id.root_hash, parser);
parse(zero_state_id.file_hash, parser);
}
template <class StorerT>
void store(const ton::BlockId &block_id, StorerT &storer) {
using td::store;
using tonlib::store;
store(block_id.workchain, storer);
store(block_id.shard, storer);
store(block_id.seqno, storer);
}
template <class ParserT>
void parse(ton::BlockId &block_id, ParserT &parser) {
using td::parse;
using tonlib::parse;
parse(block_id.workchain, parser);
parse(block_id.shard, parser);
parse(block_id.seqno, parser);
}
template <class StorerT>
void store(const ton::BlockIdExt &block_id, StorerT &storer) {
using td::store;
using tonlib::store;
store(block_id.id, storer);
store(block_id.root_hash, storer);
store(block_id.file_hash, storer);
}
template <class ParserT>
void parse(ton::BlockIdExt &block_id, ParserT &parser) {
using td::parse;
using tonlib::parse;
parse(block_id.id, parser);
parse(block_id.root_hash, parser);
parse(block_id.file_hash, parser);
}
struct LastBlockState {
ton::ZeroStateIdExt zero_state_id;
ton::BlockIdExt last_key_block_id;
ton::BlockIdExt last_block_id;
td::int64 utime{0};
ton::BlockIdExt init_block_id;
td::int32 vert_seqno{0};
static constexpr td::int32 magic = 0xa7f171a4;
enum Version { None = 0, Magic, InitBlock, VertSeqno, Next };
static constexpr td::int32 version = Version::Next - 1;
template <class StorerT>
void store(StorerT &storer) const {
using td::store;
using tonlib::store;
store(magic, storer);
store(version, storer);
store(zero_state_id, storer);
store(last_key_block_id, storer);
store(last_block_id, storer);
store(utime, storer);
store(init_block_id, storer);
store(vert_seqno, storer);
}
template <class ParserT>
void parse(ParserT &parser) {
using td::parse;
using tonlib::parse;
td::int32 version = 0;
if (parser.can_prefetch_int() && parser.prefetch_int_unsafe() == magic) {
td::int32 magic;
parse(magic, parser);
parse(version, parser);
}
parse(zero_state_id, parser);
parse(last_key_block_id, parser);
parse(last_block_id, parser);
parse(utime, parser);
if (version >= InitBlock) {
parse(init_block_id, parser);
}
if (version >= VertSeqno) {
parse(vert_seqno, parser);
}
}
};
struct LastBlockSyncState {
enum Type { Invalid, InProgress, Done } type = Invalid;
td::int32 from_seqno{0};
td::int32 to_seqno{0};
td::int32 current_seqno{0};
auto as_key() const {
return std::tie(type, from_seqno, to_seqno, current_seqno);
}
bool operator==(const LastBlockSyncState &other) const {
return as_key() == other.as_key();
}
};
class LastBlock : public td::actor::Actor {
public:
class Callback {
public:
virtual ~Callback() {
}
virtual void on_state_changed(LastBlockState state) = 0;
virtual void on_sync_state_changed(LastBlockSyncState state) = 0;
};
explicit LastBlock(ExtClientRef client, LastBlockState state, Config config, td::CancellationToken cancellation_token,
td::unique_ptr<Callback> callback);
void get_last_block(td::Promise<LastBlockState> promise);
private:
td::unique_ptr<Callback> callback_;
ExtClient client_;
LastBlockState state_;
Config config_;
td::CancellationToken cancellation_token_;
td::Status fatal_error_;
enum class QueryState { Empty, Active, Done };
QueryState get_mc_info_state_{QueryState::Empty}; // just to check zero state
QueryState check_init_block_state_{QueryState::Empty}; // init_block <---> last_key_block (from older to newer)
QueryState get_last_block_state_{QueryState::Empty}; // last_key_block_id --> ?
unsigned min_seqno_ = 0;
unsigned current_seqno_ = 0;
unsigned max_seqno_ = 0;
LastBlockSyncState sync_state_;
// stats
struct Stats {
td::Timer total_sync_;
td::Timer validate_;
td::uint32 queries_;
void start() {
total_sync_ = td::Timer();
validate_ = td::Timer(true);
queries_ = 0;
}
friend td::StringBuilder &operator<<(td::StringBuilder &sb, const Stats &stats) {
return sb << " net queries: " << stats.queries_ << "\n"
<< " total: " << stats.total_sync_ << " validation: " << stats.validate_;
}
};
Stats check_init_block_stats_;
Stats get_last_block_stats_;
std::vector<td::Promise<LastBlockState>> promises_;
void do_check_init_block(ton::BlockIdExt from, ton::BlockIdExt to);
void on_init_block_proof(
ton::BlockIdExt from, ton::BlockIdExt to,
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof>> r_block_proof);
void on_masterchain_info(td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_masterchainInfo>> r_info);
void do_get_last_block();
void on_block_proof(ton::BlockIdExt from,
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof>> r_block_proof);
td::Result<std::unique_ptr<block::BlockProofChain>> process_block_proof(
ton::BlockIdExt from,
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof>> r_block_proof);
td::Result<std::unique_ptr<block::BlockProofChain>> process_block_proof(
ton::BlockIdExt from, ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof> block_proof);
void update_state(block::BlockProofChain &chain);
void update_zero_state(ton::ZeroStateIdExt zero_state_id, td::Slice source);
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);
bool has_fatal_error() const;
LastBlockSyncState get_sync_state();
void update_sync_state();
void sync_loop();
void tear_down() override;
};
} // namespace tonlib