/* 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 . Copyright 2017-2019 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 #include namespace ton { namespace validator { using td::Ref; class Collator final : public td::actor::Actor { 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}; UnixTime min_ts; BlockIdExt min_mc_block_id; std::vector prev_blocks; std::vector> prev_states; std::vector> prev_block_data; Ed25519_PublicKey created_by_; Ref validator_set; td::actor::ActorId manager; td::Timestamp timeout; td::Promise 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, td::uint32 min_ts, BlockIdExt min_masterchain_block_id, std::vector prev, Ref validator_set, Ed25519_PublicKey collator_id, td::actor::ActorId manager, td::Timestamp timeout, td::Promise 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; } 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 mc_state_; Ref prev_mc_block; BlockIdExt mc_block_id_; Ref mc_state_root; Ref mc_block_root; td::BitArray<256> rand_seed_; std::unique_ptr config_; std::unique_ptr shard_conf_; std::map> aux_mc_states_; std::vector neighbors_; std::unique_ptr nb_out_msgs_; std::vector special_smcs; std::vector> ticktock_smcs; Ref prev_block_root; Ref prev_state_root_, prev_state_root_pure_; Ref state_root; // (new) shardchain state Ref state_update; // Merkle update from prev_state_root to state_root std::shared_ptr state_usage_tree_; // used to construct Merkle update Ref new_config_params_; 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}; td::uint64 overload_history_{0}, underload_history_{0}; td::uint64 block_size_estimate_{}; Ref wc_info_; std::vector> shard_block_descr_; std::vector> used_shard_block_descr_; std::unique_ptr shard_libraries_; Ref mc_state_extra_; std::unique_ptr account_dict; std::map> accounts; std::vector 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_limits_; std::unique_ptr block_limit_status_; ton::LogicalTime min_new_msg_lt{std::numeric_limits::max()}; block::CurrencyCollection total_balance_, old_total_balance_, total_validator_fees_; block::CurrencyCollection global_balance_, old_global_balance_, import_created_{0}; Ref recover_create_msg_, mint_msg_; Ref new_block; block::ValueFlow value_flow_{block::ValueFlow::SetZero()}; std::unique_ptr fees_import_dict_; std::map ext_msg_map; std::vector, ExtMessage::Hash>> ext_msg_list_; std::priority_queue, std::greater> new_msgs; std::pair last_proc_int_msg_, first_unproc_int_msg_; std::unique_ptr in_msg_dict, out_msg_dict, out_msg_queue_, sibling_out_msg_queue_; std::unique_ptr ihr_pending; std::shared_ptr processed_upto_, sibling_processed_upto_; std::unique_ptr block_create_stats_; std::map block_create_count_; unsigned block_create_total_{0}; std::vector bad_ext_msgs_, delay_ext_msgs_; Ref shard_account_blocks_; // ShardAccountBlocks std::vector> collated_roots_; std::unique_ptr block_candidate; td::PerfWarningTimer perf_timer_{"collate", 0.1}; // block::Account* lookup_account(td::ConstBitPtr addr) const; std::unique_ptr make_account_from(td::ConstBitPtr addr, Ref account, Ref extra, bool force_create = false); td::Result make_account(td::ConstBitPtr addr, bool force_create = false); td::actor::ActorId 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, BlockIdExt>> res); void after_get_shard_state(int idx, td::Result> res); void after_get_block_data(int idx, td::Result> res); void after_get_shard_blocks(td::Result>> res); bool preprocess_prev_mc_state(); bool register_mc_state(Ref other_mc_state); bool request_aux_mc_state(BlockSeqno seqno, Ref& state); Ref get_aux_mc_state(BlockSeqno seqno) const; void after_get_aux_shard_state(ton::BlockIdExt blkid, td::Result> 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> res); bool adjust_shard_config(); bool store_shard_fees(ShardIdFull shard, const block::CurrencyCollection& fees, const block::CurrencyCollection& created); bool store_shard_fees(Ref descr); bool import_new_shard_top_blocks(); bool register_shard_block_creators(std::vector 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 dest_addr_cell, Ref& 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 create_ordinary_transaction(Ref msg_root); 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 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 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(); void update_max_lt(ton::LogicalTime lt); bool is_masterchain() const { return shard.is_masterchain(); } bool is_our_address(Ref 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>> res); td::Result register_external_message_cell(Ref ext_msg, const ExtMessage::Hash& ext_hash); // td::Result register_external_message(td::Slice ext_msg_boc); td::Result register_ihr_message_cell(Ref ihr_msg); td::Result register_ihr_message(td::Slice ihr_msg_boc); td::Result register_shard_signatures_cell(Ref shard_blk_signatures); td::Result register_shard_signatures(td::Slice shard_blk_signatures_boc); void register_new_msg(block::NewOutMsg msg); void register_new_msgs(block::Transaction& trans); bool process_new_messages(bool enqueue_only = false); int process_one_new_message(block::NewOutMsg msg, bool enqueue_only = false, Ref* is_special = nullptr); bool process_inbound_internal_messages(); bool process_inbound_message(Ref msg, ton::LogicalTime lt, td::ConstBitPtr key, const block::McShardDescr& src_nb); bool process_inbound_external_messages(); int process_external_message(Ref msg); bool enqueue_message(block::NewOutMsg msg, td::RefInt256 fwd_fees_remaining, ton::LogicalTime enqueued_lt); bool enqueue_transit_message(Ref msg, Ref old_msg_env, ton::AccountIdPrefixFull prev_prefix, ton::AccountIdPrefixFull cur_prefix, ton::AccountIdPrefixFull dest_prefix, td::RefInt256 fwd_fee_remaining, ton::LogicalTime enqueued_lt); bool delete_out_msg_queue_msg(td::ConstBitPtr key); bool insert_in_msg(Ref in_msg); bool insert_out_msg(Ref out_msg); 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 orig_libs, Ref final_libs, const td::Bits256& addr); bool add_public_library(td::ConstBitPtr key, td::ConstBitPtr addr, Ref 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> get_config_data_from_smc(const ton::StdSmcAddress& cfg_addr); bool try_fetch_new_config(const ton::StdSmcAddress& cfg_addr, Ref& new_config); bool update_processed_upto(); bool compute_out_msg_queue_info(Ref& 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 create_block_info(Ref& block_info); bool check_value_flow(); bool create_block_extra(Ref& block_extra); bool update_shard_config(const block::WorkchainSet& wc_set, const block::CatchainValidatorsConfig& ccvc, bool update_cc); bool create_mc_block_extra(Ref& mc_block_extra); bool create_block(); Ref collate_shard_block_descr_set(); bool create_collated_data(); bool create_block_candidate(); void return_block_candidate(td::Result saved); bool update_last_proc_int_msg(const std::pair& new_lt_hash); }; } // namespace validator } // namespace ton