1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-13 11:42:18 +00:00
ton/validator/impl/collator-impl.h
EmelyanenkoK 0434eadc1f
Add custom overlays for external messages (#949)
* Private overlay for external messages

* Improve ext msg overlays

* Manage from validator console
* Bypass out queue size limit for high-priority messages
* Shuffle messages in get_external_messages

* Cleanup mempool when creating validator group

* Improve private overlays for externals

1. Allow using validator adnl ids in addition to fullnode ids
2. Set priority per sender, not per overlay
3. Require the same overlay name for all nodes
4. Enable lz4 in private block overlay

* Fix typo, add debug logs

* Enable lz4 in private block overlay by config

Change proto_version for lz4 in catchain overlays to 4

* Add logs for broadcasts in fullnode

---------

Co-authored-by: SpyCheese <mikle98@yandex.ru>
2024-04-01 16:44:08 +03:00

338 lines
16 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 "interfaces/validator-manager.h"
#include "shard.hpp"
#include "top-shard-descr.hpp"
#include "common/refcnt.hpp"
#include "vm/cells.h"
#include "vm/dict.h"
#include "block/mc-config.h"
#include "block/block.h"
#include "block/transaction.h"
#include "block/block-db.h"
#include "block/output-queue-merger.h"
#include "vm/cells/MerkleProof.h"
#include "vm/cells/MerkleUpdate.h"
#include <map>
#include <queue>
#include "common/global-version.h"
namespace ton {
namespace validator {
using td::Ref;
class Collator final : public td::actor::Actor {
static constexpr int supported_version() {
return SUPPORTED_VERSION;
}
static constexpr long long supported_capabilities() {
return ton::capCreateStatsEnabled | ton::capBounceMsgBody | ton::capReportVersion | ton::capShortDequeue;
}
using LtCellRef = block::LtCellRef;
using NewOutMsg = block::NewOutMsg;
const ShardIdFull shard_;
ton::BlockId new_id;
bool busy_{false};
bool before_split_{false};
bool after_split_{false};
bool after_merge_{false};
bool want_split_{false};
bool want_merge_{false};
bool right_child_{false};
bool preinit_complete{false};
bool is_key_block_{false};
bool block_full_{false};
bool inbound_queues_empty_{false};
bool libraries_changed_{false};
bool prev_key_block_exists_{false};
bool is_hardfork_{false};
UnixTime min_ts;
BlockIdExt min_mc_block_id;
std::vector<BlockIdExt> prev_blocks;
std::vector<Ref<ShardState>> prev_states;
std::vector<Ref<BlockData>> prev_block_data;
Ed25519_PublicKey created_by_;
Ref<ValidatorSet> validator_set_;
td::actor::ActorId<ValidatorManager> manager;
td::Timestamp timeout;
td::Timestamp queue_cleanup_timeout_, soft_timeout_, medium_timeout_;
td::Promise<BlockCandidate> main_promise;
ton::BlockSeqno last_block_seqno{0};
ton::BlockSeqno prev_mc_block_seqno{0};
ton::BlockSeqno new_block_seqno{0};
ton::BlockSeqno prev_key_block_seqno_{0};
int step{0};
int pending{0};
static constexpr int max_ihr_msg_size = 65535; // 64k
static constexpr int max_ext_msg_size = 65535; // 64k
static constexpr int max_blk_sign_size = 65535; // 64k
static constexpr bool shard_splitting_enabled = true;
public:
Collator(ShardIdFull shard, bool is_hardfork, td::uint32 min_ts, BlockIdExt min_masterchain_block_id,
std::vector<BlockIdExt> prev, Ref<ValidatorSet> validator_set, Ed25519_PublicKey collator_id,
td::actor::ActorId<ValidatorManager> manager, td::Timestamp timeout, td::Promise<BlockCandidate> promise);
~Collator() override = default;
bool is_busy() const {
return busy_;
}
ShardId get_shard() const {
return shard_.shard;
}
WorkchainId workchain() const {
return shard_.workchain;
}
static constexpr td::uint32 priority() {
return 2;
}
static td::Result<std::unique_ptr<block::transaction::Transaction>>
impl_create_ordinary_transaction(Ref<vm::Cell> msg_root,
block::Account* acc,
UnixTime utime, LogicalTime lt,
block::StoragePhaseConfig* storage_phase_cfg,
block::ComputePhaseConfig* compute_phase_cfg,
block::ActionPhaseConfig* action_phase_cfg,
bool external, LogicalTime after_lt);
private:
void start_up() override;
void alarm() override;
int verbosity{3 * 0};
int verify{1};
ton::LogicalTime start_lt, max_lt;
ton::UnixTime now_;
ton::UnixTime prev_now_;
ton::UnixTime now_upper_limit_{~0U};
unsigned out_msg_queue_ops_{}, in_descr_cnt_{}, out_descr_cnt_{};
Ref<MasterchainStateQ> mc_state_;
Ref<BlockData> prev_mc_block;
BlockIdExt mc_block_id_;
Ref<vm::Cell> mc_state_root;
Ref<vm::Cell> mc_block_root;
td::BitArray<256> rand_seed_ = td::Bits256::zero();
std::unique_ptr<block::ConfigInfo> config_;
std::unique_ptr<block::ShardConfig> shard_conf_;
std::map<BlockSeqno, Ref<MasterchainStateQ>> aux_mc_states_;
std::vector<block::McShardDescr> neighbors_;
std::unique_ptr<block::OutputQueueMerger> nb_out_msgs_;
std::vector<ton::StdSmcAddress> special_smcs;
std::vector<std::pair<ton::StdSmcAddress, int>> ticktock_smcs;
Ref<vm::Cell> prev_block_root;
Ref<vm::Cell> prev_state_root_, prev_state_root_pure_;
Ref<vm::Cell> state_root; // (new) shardchain state
Ref<vm::Cell> state_update; // Merkle update from prev_state_root to state_root
std::shared_ptr<vm::CellUsageTree> state_usage_tree_; // used to construct Merkle update
Ref<vm::CellSlice> new_config_params_;
Ref<vm::Cell> old_mparams_;
ton::LogicalTime prev_state_lt_;
ton::LogicalTime shards_max_end_lt_{0};
ton::UnixTime prev_state_utime_;
int global_id_{0};
ton::BlockSeqno min_ref_mc_seqno_{~0U};
ton::BlockSeqno vert_seqno_{~0U}, prev_vert_seqno_{~0U};
ton::BlockIdExt prev_key_block_;
ton::LogicalTime prev_key_block_lt_;
bool accept_msgs_{true};
bool shard_conf_adjusted_{false};
bool ihr_enabled_{false};
bool create_stats_enabled_{false};
bool report_version_{false};
bool skip_topmsgdescr_{false};
bool skip_extmsg_{false};
bool short_dequeue_records_{false};
td::uint64 overload_history_{0}, underload_history_{0};
td::uint64 block_size_estimate_{};
Ref<block::WorkchainInfo> wc_info_;
std::vector<Ref<ShardTopBlockDescription>> shard_block_descr_;
std::vector<Ref<ShardTopBlockDescrQ>> used_shard_block_descr_;
std::unique_ptr<vm::Dictionary> shard_libraries_;
Ref<vm::Cell> mc_state_extra_;
std::unique_ptr<vm::AugmentedDictionary> account_dict;
std::map<ton::StdSmcAddress, std::unique_ptr<block::Account>> accounts;
std::vector<block::StoragePrices> storage_prices_;
block::StoragePhaseConfig storage_phase_cfg_{&storage_prices_};
block::ComputePhaseConfig compute_phase_cfg_;
block::ActionPhaseConfig action_phase_cfg_;
td::RefInt256 masterchain_create_fee_, basechain_create_fee_;
std::unique_ptr<block::BlockLimits> block_limits_;
std::unique_ptr<block::BlockLimitStatus> block_limit_status_;
ton::LogicalTime min_new_msg_lt{std::numeric_limits<td::uint64>::max()};
block::CurrencyCollection total_balance_, old_total_balance_, total_validator_fees_;
block::CurrencyCollection global_balance_, old_global_balance_, import_created_{0};
Ref<vm::Cell> recover_create_msg_, mint_msg_;
Ref<vm::Cell> new_block;
block::ValueFlow value_flow_{block::ValueFlow::SetZero()};
std::unique_ptr<vm::AugmentedDictionary> fees_import_dict_;
std::map<ton::Bits256, int> ext_msg_map;
struct ExtMsg {
Ref<vm::Cell> cell;
ExtMessage::Hash hash;
int priority;
};
std::vector<ExtMsg> ext_msg_list_;
std::priority_queue<NewOutMsg, std::vector<NewOutMsg>, std::greater<NewOutMsg>> new_msgs;
std::pair<ton::LogicalTime, ton::Bits256> last_proc_int_msg_, first_unproc_int_msg_;
std::unique_ptr<vm::AugmentedDictionary> in_msg_dict, out_msg_dict, out_msg_queue_, sibling_out_msg_queue_;
td::uint32 out_msg_queue_size_ = 0;
std::unique_ptr<vm::Dictionary> ihr_pending;
std::shared_ptr<block::MsgProcessedUptoCollection> processed_upto_, sibling_processed_upto_;
std::unique_ptr<vm::Dictionary> block_create_stats_;
std::map<td::Bits256, int> block_create_count_;
unsigned block_create_total_{0};
std::vector<ExtMessage::Hash> bad_ext_msgs_, delay_ext_msgs_;
Ref<vm::Cell> shard_account_blocks_; // ShardAccountBlocks
std::vector<Ref<vm::Cell>> collated_roots_;
std::unique_ptr<ton::BlockCandidate> block_candidate;
td::PerfWarningTimer perf_timer_;
//
block::Account* lookup_account(td::ConstBitPtr addr) const;
std::unique_ptr<block::Account> make_account_from(td::ConstBitPtr addr, Ref<vm::CellSlice> account,
bool force_create);
td::Result<block::Account*> make_account(td::ConstBitPtr addr, bool force_create = false);
td::actor::ActorId<Collator> get_self() {
return actor_id(this);
}
bool init_utime();
bool init_lt();
bool fetch_config_params();
bool fatal_error(td::Status error);
bool fatal_error(int err_code, std::string err_msg);
bool fatal_error(std::string err_msg, int err_code = -666);
void check_pending();
void after_get_mc_state(td::Result<std::pair<Ref<MasterchainState>, BlockIdExt>> res);
void after_get_shard_state(int idx, td::Result<Ref<ShardState>> res);
void after_get_block_data(int idx, td::Result<Ref<BlockData>> res);
void after_get_shard_blocks(td::Result<std::vector<Ref<ShardTopBlockDescription>>> res);
bool preprocess_prev_mc_state();
bool register_mc_state(Ref<MasterchainStateQ> other_mc_state);
bool request_aux_mc_state(BlockSeqno seqno, Ref<MasterchainStateQ>& state);
Ref<MasterchainStateQ> get_aux_mc_state(BlockSeqno seqno) const;
void after_get_aux_shard_state(ton::BlockIdExt blkid, td::Result<Ref<ShardState>> res);
bool fix_one_processed_upto(block::MsgProcessedUpto& proc, const ton::ShardIdFull& owner);
bool fix_processed_upto(block::MsgProcessedUptoCollection& upto);
void got_neighbor_out_queue(int i, td::Result<Ref<MessageQueue>> res);
void got_out_queue_size(size_t i, td::Result<td::uint32> res);
bool adjust_shard_config();
bool store_shard_fees(ShardIdFull shard, const block::CurrencyCollection& fees,
const block::CurrencyCollection& created);
bool store_shard_fees(Ref<block::McShardHash> descr);
bool import_new_shard_top_blocks();
bool register_shard_block_creators(std::vector<td::Bits256> creator_list);
bool init_block_limits();
bool compute_minted_amount(block::CurrencyCollection& to_mint);
bool init_value_create();
bool try_collate();
bool do_preinit();
bool do_collate();
bool create_special_transactions();
bool create_special_transaction(block::CurrencyCollection amount, Ref<vm::Cell> dest_addr_cell,
Ref<vm::Cell>& in_msg);
bool create_ticktock_transactions(int mask);
bool create_ticktock_transaction(const ton::StdSmcAddress& smc_addr, ton::LogicalTime req_start_lt, int mask);
Ref<vm::Cell> create_ordinary_transaction(Ref<vm::Cell> msg_root, bool is_special_tx = false);
bool check_cur_validator_set();
bool unpack_last_mc_state();
bool unpack_last_state();
bool unpack_merge_last_state();
bool unpack_one_last_state(block::ShardState& ss, BlockIdExt blkid, Ref<vm::Cell> prev_state_root);
bool split_last_state(block::ShardState& ss);
bool import_shard_state_data(block::ShardState& ss);
bool add_trivial_neighbor();
bool add_trivial_neighbor_after_merge();
bool out_msg_queue_cleanup();
bool dequeue_message(Ref<vm::Cell> msg_envelope, ton::LogicalTime delivered_lt);
bool check_prev_block(const BlockIdExt& listed, const BlockIdExt& prev, bool chk_chain_len = true);
bool check_prev_block_exact(const BlockIdExt& listed, const BlockIdExt& prev);
bool check_this_shard_mc_info();
bool request_neighbor_msg_queues();
bool request_out_msg_queue_size();
void update_max_lt(ton::LogicalTime lt);
bool is_masterchain() const {
return shard_.is_masterchain();
}
bool is_our_address(Ref<vm::CellSlice> addr_ref) const;
bool is_our_address(ton::AccountIdPrefixFull addr_prefix) const;
bool is_our_address(const ton::StdSmcAddress& addr) const;
void after_get_external_messages(td::Result<std::vector<std::pair<Ref<ExtMessage>, int>>> res);
td::Result<bool> register_external_message_cell(Ref<vm::Cell> ext_msg, const ExtMessage::Hash& ext_hash,
int priority);
// td::Result<bool> register_external_message(td::Slice ext_msg_boc);
void register_new_msg(block::NewOutMsg msg);
void register_new_msgs(block::transaction::Transaction& trans);
bool process_new_messages(bool enqueue_only = false);
int process_one_new_message(block::NewOutMsg msg, bool enqueue_only = false, Ref<vm::Cell>* is_special = nullptr);
bool process_inbound_internal_messages();
bool process_inbound_message(Ref<vm::CellSlice> msg, ton::LogicalTime lt, td::ConstBitPtr key,
const block::McShardDescr& src_nb);
bool process_inbound_external_messages();
int process_external_message(Ref<vm::Cell> msg);
bool enqueue_message(block::NewOutMsg msg, td::RefInt256 fwd_fees_remaining, ton::LogicalTime enqueued_lt);
bool enqueue_transit_message(Ref<vm::Cell> msg, Ref<vm::Cell> old_msg_env, ton::AccountIdPrefixFull prev_prefix,
ton::AccountIdPrefixFull cur_prefix, ton::AccountIdPrefixFull dest_prefix,
td::RefInt256 fwd_fee_remaining);
bool delete_out_msg_queue_msg(td::ConstBitPtr key);
bool insert_in_msg(Ref<vm::Cell> in_msg);
bool insert_out_msg(Ref<vm::Cell> out_msg);
bool insert_out_msg(Ref<vm::Cell> out_msg, td::ConstBitPtr msg_hash);
bool register_out_msg_queue_op(bool force = false);
bool update_min_mc_seqno(ton::BlockSeqno some_mc_seqno);
bool combine_account_transactions();
bool update_public_libraries();
bool update_account_public_libraries(Ref<vm::Cell> orig_libs, Ref<vm::Cell> final_libs, const td::Bits256& addr);
bool add_public_library(td::ConstBitPtr key, td::ConstBitPtr addr, Ref<vm::Cell> library);
bool remove_public_library(td::ConstBitPtr key, td::ConstBitPtr addr);
bool check_block_overload();
bool update_block_creator_count(td::ConstBitPtr key, unsigned shard_incr, unsigned mc_incr);
int creator_count_outdated(td::ConstBitPtr key, vm::CellSlice& cs);
bool update_block_creator_stats();
bool create_mc_state_extra();
bool create_shard_state();
td::Result<Ref<vm::Cell>> get_config_data_from_smc(const ton::StdSmcAddress& cfg_addr);
bool try_fetch_new_config(const ton::StdSmcAddress& cfg_addr, Ref<vm::Cell>& new_config);
bool update_processed_upto();
bool compute_out_msg_queue_info(Ref<vm::Cell>& out_msg_queue_info);
bool compute_total_balance();
bool store_master_ref(vm::CellBuilder& cb);
bool store_prev_blk_ref(vm::CellBuilder& cb, bool after_merge);
bool store_zero_state_ref(vm::CellBuilder& cb);
bool store_version(vm::CellBuilder& cb) const;
bool create_block_info(Ref<vm::Cell>& block_info);
bool check_value_flow();
bool create_block_extra(Ref<vm::Cell>& block_extra);
bool update_shard_config(const block::WorkchainSet& wc_set, const block::CatchainValidatorsConfig& ccvc,
bool update_cc);
bool create_mc_block_extra(Ref<vm::Cell>& mc_block_extra);
bool create_block();
Ref<vm::Cell> collate_shard_block_descr_set();
bool create_collated_data();
bool create_block_candidate();
void return_block_candidate(td::Result<td::Unit> saved);
bool update_last_proc_int_msg(const std::pair<ton::LogicalTime, ton::Bits256>& new_lt_hash);
public:
static td::uint32 get_skip_externals_queue_size();
};
} // namespace validator
} // namespace ton