From 2ce2c8fc49f04e7d28f9b09175a7ce41f60ae516 Mon Sep 17 00:00:00 2001 From: SpyCheese Date: Sat, 12 Oct 2024 13:21:47 +0300 Subject: [PATCH] Count account_dict size in block size estimation (#1261) * Count account_dict size in block size estimation * Fix updating account dict estimator --- crypto/block/block.cpp | 4 ++-- validator/impl/collator-impl.h | 5 ++++ validator/impl/collator.cpp | 43 +++++++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/crypto/block/block.cpp b/crypto/block/block.cpp index cb371fa0b..6b9ca8bf0 100644 --- a/crypto/block/block.cpp +++ b/crypto/block/block.cpp @@ -719,8 +719,8 @@ td::uint64 BlockLimitStatus::estimate_block_size(const vm::NewCellStorageStat::S if (extra) { sum += *extra; } - return 2000 + (sum.bits >> 3) + sum.cells * 12 + sum.internal_refs * 3 + sum.external_refs * 40 + accounts * 200 + - transactions * 200 + (extra ? 200 : 0) + extra_out_msgs * 300 + public_library_diff * 700; + return 2000 + (sum.bits >> 3) + sum.cells * 12 + sum.internal_refs * 3 + sum.external_refs * 40 + transactions * 200 + + (extra ? 200 : 0) + extra_out_msgs * 300 + public_library_diff * 700; } int BlockLimitStatus::classify() const { diff --git a/validator/impl/collator-impl.h b/validator/impl/collator-impl.h index ea1695f35..b1594a4cc 100644 --- a/validator/impl/collator-impl.h +++ b/validator/impl/collator-impl.h @@ -220,6 +220,10 @@ class Collator final : public td::actor::Actor { td::uint64 defer_out_queue_size_limit_; td::uint64 hard_defer_out_queue_size_limit_; + std::unique_ptr account_dict_estimator_; + std::set account_dict_estimator_added_accounts_; + unsigned account_dict_ops_{0}; + bool msg_metadata_enabled_ = false; bool deferring_messages_enabled_ = false; bool store_out_msg_queue_size_ = false; @@ -323,6 +327,7 @@ class Collator final : public td::actor::Actor { bool insert_out_msg(Ref out_msg, td::ConstBitPtr msg_hash); bool register_out_msg_queue_op(bool force = false); bool register_dispatch_queue_op(bool force = false); + bool update_account_dict_estimation(const block::transaction::Transaction& trans); bool update_min_mc_seqno(ton::BlockSeqno some_mc_seqno); bool combine_account_transactions(); bool update_public_libraries(); diff --git a/validator/impl/collator.cpp b/validator/impl/collator.cpp index 12cee057f..0708fb527 100644 --- a/validator/impl/collator.cpp +++ b/validator/impl/collator.cpp @@ -1064,7 +1064,7 @@ bool Collator::split_last_state(block::ShardState& ss) { /** * Imports the shard state data into the Collator object. * - * SETS: account_dict, shard_libraries_, mc_state_extra + * SETS: account_dict = account_dict_estimator_, shard_libraries_, mc_state_extra * total_balance_ = old_total_balance_, total_validator_fees_ * SETS: overload_history_, underload_history_ * SETS: prev_state_utime_, prev_state_lt_, prev_vert_seqno_ @@ -1076,6 +1076,7 @@ bool Collator::split_last_state(block::ShardState& ss) { */ bool Collator::import_shard_state_data(block::ShardState& ss) { account_dict = std::move(ss.account_dict_); + account_dict_estimator_ = std::make_unique(*account_dict); shard_libraries_ = std::move(ss.shard_libraries_); mc_state_extra_ = std::move(ss.mc_state_extra_); overload_history_ = ss.overload_history_; @@ -2742,6 +2743,9 @@ bool Collator::create_ticktock_transaction(const ton::StdSmcAddress& smc_addr, t return fatal_error( td::Status::Error(-666, std::string{"cannot commit new transaction for smart contract "} + smc_addr.to_hex())); } + if (!update_account_dict_estimation(*trans)) { + return fatal_error(-666, "cannot update account dict size estimation"); + } update_max_lt(acc->last_trans_end_lt_); block::MsgMetadata new_msg_metadata{0, acc->workchain, acc->addr, trans->start_lt}; register_new_msgs(*trans, std::move(new_msg_metadata)); @@ -2835,6 +2839,10 @@ Ref Collator::create_ordinary_transaction(Ref msg_root, fatal_error("cannot commit new transaction for smart contract "s + addr.to_hex()); return {}; } + if (!update_account_dict_estimation(*trans)) { + fatal_error("cannot update account dict size estimation"); + return {}; + } td::optional new_msg_metadata; if (external || is_special_tx) { @@ -5038,6 +5046,39 @@ bool Collator::register_dispatch_queue_op(bool force) { } } +/** + * Update size estimation for the account dictionary. + * This is required to count the depth of the ShardAccounts dictionary in the block size estimation. + * account_dict_estimator_ is used for block limits only. + * + * @param trans Newly-created transaction. + * + * @returns True on success, false otherwise. + */ +bool Collator::update_account_dict_estimation(const block::transaction::Transaction& trans) { + const block::Account& acc = trans.account; + if (acc.orig_total_state->get_hash() != acc.total_state->get_hash() && + account_dict_estimator_added_accounts_.insert(acc.addr).second) { + // see combine_account_transactions + if (acc.status == block::Account::acc_nonexist) { + account_dict_estimator_->lookup_delete(acc.addr); + } else { + vm::CellBuilder cb; + if (!(cb.store_ref_bool(acc.total_state) // account_descr$_ account:^Account + && cb.store_bits_bool(acc.last_trans_hash_) // last_trans_hash:bits256 + && cb.store_long_bool(acc.last_trans_lt_, 64) // last_trans_lt:uint64 + && account_dict_estimator_->set_builder(acc.addr, cb))) { + return false; + } + } + } + ++account_dict_ops_; + if (!(account_dict_ops_ & 15)) { + return block_limit_status_->add_proof(account_dict_estimator_->get_root_cell()); + } + return true; +} + /** * Creates a new shard state and the Merkle update. *