1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

Count gas usage for ordinar transactions on special accounts in separate counter (#872)

* Improve checking total gas usage in collator and validator

---------

Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
EmelyanenkoK 2024-01-22 21:56:11 +03:00 committed by GitHub
parent d91643face
commit 2e231ec2ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 28 additions and 13 deletions

View file

@ -244,7 +244,7 @@ class Collator final : public td::actor::Actor {
Ref<vm::Cell>& in_msg); Ref<vm::Cell>& in_msg);
bool create_ticktock_transactions(int mask); bool create_ticktock_transactions(int mask);
bool create_ticktock_transaction(const ton::StdSmcAddress& smc_addr, ton::LogicalTime req_start_lt, 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); Ref<vm::Cell> create_ordinary_transaction(Ref<vm::Cell> msg_root, bool is_special_tx = false);
bool check_cur_validator_set(); bool check_cur_validator_set();
bool unpack_last_mc_state(); bool unpack_last_mc_state();
bool unpack_last_state(); bool unpack_last_state();

View file

@ -2667,8 +2667,7 @@ bool Collator::create_ticktock_transaction(const ton::StdSmcAddress& smc_addr, t
return fatal_error(td::Status::Error( return fatal_error(td::Status::Error(
-666, std::string{"cannot serialize new transaction for smart contract "} + smc_addr.to_hex())); -666, std::string{"cannot serialize new transaction for smart contract "} + smc_addr.to_hex()));
} }
if (!trans->update_limits(*block_limit_status_, if (!trans->update_limits(*block_limit_status_, /* with_gas = */ false)) {
/* with_gas = */ !(acc->is_special && compute_phase_cfg_.special_gas_full))) {
return fatal_error(-666, "cannot update block limit status to include the new transaction"); return fatal_error(-666, "cannot update block limit status to include the new transaction");
} }
if (trans->commit(*acc).is_null()) { if (trans->commit(*acc).is_null()) {
@ -2684,10 +2683,11 @@ bool Collator::create_ticktock_transaction(const ton::StdSmcAddress& smc_addr, t
* Creates an ordinary transaction using a given message. * Creates an ordinary transaction using a given message.
* *
* @param msg_root The root of the message to be processed serialized using Message TLB-scheme. * @param msg_root The root of the message to be processed serialized using Message TLB-scheme.
* @param is_special_tx True if creating a special transaction (mint/recover), false otherwise.
* *
* @returns The root of the serialized transaction, or an empty reference if the transaction creation fails. * @returns The root of the serialized transaction, or an empty reference if the transaction creation fails.
*/ */
Ref<vm::Cell> Collator::create_ordinary_transaction(Ref<vm::Cell> msg_root) { Ref<vm::Cell> Collator::create_ordinary_transaction(Ref<vm::Cell> msg_root, bool is_special_tx) {
ton::StdSmcAddress addr; ton::StdSmcAddress addr;
auto cs = vm::load_cell_slice(msg_root); auto cs = vm::load_cell_slice(msg_root);
bool external; bool external;
@ -2746,7 +2746,7 @@ Ref<vm::Cell> Collator::create_ordinary_transaction(Ref<vm::Cell> msg_root) {
std::unique_ptr<block::transaction::Transaction> trans = res.move_as_ok(); std::unique_ptr<block::transaction::Transaction> trans = res.move_as_ok();
if (!trans->update_limits(*block_limit_status_, if (!trans->update_limits(*block_limit_status_,
/* with_gas = */ !(acc->is_special && compute_phase_cfg_.special_gas_full))) { /* with_gas = */ !(is_special_tx && compute_phase_cfg_.special_gas_full))) {
fatal_error("cannot update block limit status to include the new transaction"); fatal_error("cannot update block limit status to include the new transaction");
return {}; return {};
} }
@ -3019,7 +3019,7 @@ int Collator::process_one_new_message(block::NewOutMsg msg, bool enqueue_only, R
return -1; return -1;
} }
// 1. create a Transaction processing this Message // 1. create a Transaction processing this Message
auto trans_root = create_ordinary_transaction(msg.msg); auto trans_root = create_ordinary_transaction(msg.msg, is_special != nullptr);
if (trans_root.is_null()) { if (trans_root.is_null()) {
fatal_error("cannot create transaction for re-processing output message"); fatal_error("cannot create transaction for re-processing output message");
return -1; return -1;

View file

@ -4685,6 +4685,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT
bool external{false}, ihr_delivered{false}, need_credit_phase{false}; bool external{false}, ihr_delivered{false}, need_credit_phase{false};
// check input message // check input message
block::CurrencyCollection money_imported(0), money_exported(0); block::CurrencyCollection money_imported(0), money_exported(0);
bool is_special_tx = false; // recover/mint transaction
if (in_msg_root.not_null()) { if (in_msg_root.not_null()) {
auto in_descr_cs = in_msg_dict_->lookup(in_msg_root->get_hash().as_bitslice()); auto in_descr_cs = in_msg_dict_->lookup(in_msg_root->get_hash().as_bitslice());
if (in_descr_cs.is_null()) { if (in_descr_cs.is_null()) {
@ -4700,6 +4701,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT
<< " has an invalid InMsg record (not one of msg_import_ext, msg_import_fin, " << " has an invalid InMsg record (not one of msg_import_ext, msg_import_fin, "
"msg_import_imm or msg_import_ihr)"); "msg_import_imm or msg_import_ihr)");
} }
is_special_tx = is_special_in_msg(*in_descr_cs);
// once we know there is a InMsg with correct hash, we already know that it contains a message with this hash (by the verification of InMsg), so it is our message // once we know there is a InMsg with correct hash, we already know that it contains a message with this hash (by the verification of InMsg), so it is our message
// have still to check its destination address and imported value // have still to check its destination address and imported value
// and that it refers to this transaction // and that it refers to this transaction
@ -4717,7 +4719,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT
<< " processed inbound message created later at logical time " << " processed inbound message created later at logical time "
<< info.created_lt); << info.created_lt);
} }
if (info.created_lt != start_lt_ || !is_special_in_msg(*in_descr_cs)) { if (info.created_lt != start_lt_ || !is_special_tx) {
msg_proc_lt_.emplace_back(addr, lt, info.created_lt); msg_proc_lt_.emplace_back(addr, lt, info.created_lt);
} }
dest = std::move(info.dest); dest = std::move(info.dest);
@ -5057,19 +5059,31 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT
return reject_query(PSTRING() << "cannot re-create the serialization of transaction " << lt return reject_query(PSTRING() << "cannot re-create the serialization of transaction " << lt
<< " for smart contract " << addr.to_hex()); << " for smart contract " << addr.to_hex());
} }
if (!trs->update_limits(*block_limit_status_, if (!trs->update_limits(*block_limit_status_, /* with_gas = */ false, /* with_size = */ false)) {
/* with_gas = */ !account.is_special && !trs->gas_limit_overridden,
/* with_size = */ false)) {
return fatal_error(PSTRING() << "cannot update block limit status to include transaction " << lt << " of account " return fatal_error(PSTRING() << "cannot update block limit status to include transaction " << lt << " of account "
<< addr.to_hex()); << addr.to_hex());
} }
if (block_limit_status_->gas_used > block_limits_->gas.hard() + compute_phase_cfg_.gas_limit) {
// Note that block_limit_status_->gas_used does not include transactions in special accounts // Collator should stop if total gas usage exceeds limits, including transactions on special accounts, but without
// ticktocks and mint/recover.
// Here Validator checks a weaker condition
if (!is_special_tx && !trs->gas_limit_overridden && trans_type == block::transaction::Transaction::tr_ord) {
(account.is_special ? total_special_gas_used_ : total_gas_used_) += trs->gas_used();
}
if (total_gas_used_ > block_limits_->gas.hard() + compute_phase_cfg_.gas_limit) {
return reject_query(PSTRING() << "gas block limits are exceeded: total_gas_used > gas_limit_hard + trx_gas_limit (" return reject_query(PSTRING() << "gas block limits are exceeded: total_gas_used > gas_limit_hard + trx_gas_limit ("
<< "total_gas_used=" << block_limit_status_->gas_used << "total_gas_used=" << total_gas_used_
<< ", gas_limit_hard=" << block_limits_->gas.hard() << ", gas_limit_hard=" << block_limits_->gas.hard()
<< ", trx_gas_limit=" << compute_phase_cfg_.gas_limit << ")"); << ", trx_gas_limit=" << compute_phase_cfg_.gas_limit << ")");
} }
if (total_special_gas_used_ > block_limits_->gas.hard() + compute_phase_cfg_.special_gas_limit) {
return reject_query(
PSTRING() << "gas block limits are exceeded: total_special_gas_used > gas_limit_hard + special_gas_limit ("
<< "total_special_gas_used=" << total_special_gas_used_
<< ", gas_limit_hard=" << block_limits_->gas.hard()
<< ", special_gas_limit=" << compute_phase_cfg_.special_gas_limit << ")");
}
auto trans_root2 = trs->commit(account); auto trans_root2 = trs->commit(account);
if (trans_root2.is_null()) { if (trans_root2.is_null()) {
return reject_query(PSTRING() << "the re-created transaction " << lt << " for smart contract " << addr.to_hex() return reject_query(PSTRING() << "the re-created transaction " << lt << " for smart contract " << addr.to_hex()

View file

@ -195,6 +195,7 @@ class ValidateQuery : public td::actor::Actor {
ton::LogicalTime prev_key_block_lt_; ton::LogicalTime prev_key_block_lt_;
std::unique_ptr<block::BlockLimits> block_limits_; std::unique_ptr<block::BlockLimits> block_limits_;
std::unique_ptr<block::BlockLimitStatus> block_limit_status_; std::unique_ptr<block::BlockLimitStatus> block_limit_status_;
td::uint64 total_gas_used_{0}, total_special_gas_used_{0};
LogicalTime start_lt_, end_lt_; LogicalTime start_lt_, end_lt_;
UnixTime prev_now_{~0u}, now_{~0u}; UnixTime prev_now_{~0u}, now_{~0u};