From ea5a02e0e41be7e2c9700e917f36b1d6a2b21e58 Mon Sep 17 00:00:00 2001 From: OmicronTau Date: Sun, 5 Dec 2021 17:44:46 +0300 Subject: [PATCH] Deactivate accounts upon destruction in block --- crypto/block/transaction.cpp | 52 ++++++++++++++++++++++--------- crypto/block/transaction.h | 11 ++++--- rldp2/CMakeLists.txt | 2 +- validator/impl/collator.cpp | 9 ------ validator/impl/validate-query.cpp | 3 +- 5 files changed, 46 insertions(+), 31 deletions(-) diff --git a/crypto/block/transaction.cpp b/crypto/block/transaction.cpp index 3668a45f3..e5cd701d7 100644 --- a/crypto/block/transaction.cpp +++ b/crypto/block/transaction.cpp @@ -271,7 +271,7 @@ bool Account::recompute_tmp_addr(Ref& tmp_addr, int split_depth, } bool Account::init_rewrite_addr(int split_depth, td::ConstBitPtr orig_addr_rewrite) { - if (split_depth_set_ || !created || !set_split_depth(split_depth)) { + if (split_depth_set_ || !set_split_depth(split_depth)) { return false; } addr_orig = addr; @@ -304,15 +304,8 @@ bool Account::unpack(Ref shard_account, Ref extra, total_state = orig_total_state = account; auto acc_cs = load_cell_slice(std::move(account)); if (block::gen::t_Account.get_tag(acc_cs) == block::gen::Account::account_none) { - status = acc_nonexist; - last_paid = 0; - last_trans_end_lt_ = 0; is_special = special; - if (workchain != ton::workchainInvalid) { - addr_orig = addr; - addr_rewrite = addr.cbits(); - } - return compute_my_addr() && acc_cs.size_ext() == 1; + return acc_cs.size_ext() == 1 && init_new(now); } block::gen::Account::Record_account acc; block::gen::AccountStorage::Record storage; @@ -328,6 +321,7 @@ bool Account::unpack(Ref shard_account, Ref extra, case block::gen::AccountState::account_uninit: status = orig_status = acc_uninit; state_hash = addr; + forget_split_depth(); break; case block::gen::AccountState::account_frozen: status = orig_status = acc_frozen; @@ -396,10 +390,42 @@ bool Account::init_new(ton::UnixTime now) { state_hash = addr_orig; status = orig_status = acc_nonexist; split_depth_set_ = false; - created = true; return true; } +bool Account::forget_split_depth() { + split_depth_set_ = false; + split_depth_ = 0; + addr_orig = addr; + my_addr = my_addr_exact; + addr_rewrite = addr.bits(); + return true; +} + +bool Account::deactivate() { + if (status == acc_active) { + return false; + } + // forget special (tick/tock) info + tick = tock = false; + if (status == acc_nonexist || status == acc_uninit) { + // forget split depth and address rewriting info + forget_split_depth(); + // forget specific state hash for deleted or uninitialized accounts (revert to addr) + state_hash = addr; + } + // forget code and data (only active accounts remember these) + code.clear(); + data.clear(); + library.clear(); + // if deleted, balance must be zero + if (status == acc_nonexist && !balance.is_zero()) { + return false; + } + return true; +} + + bool Account::belongs_to_shard(ton::ShardIdFull shard) const { return workchain == shard.workchain && ton::shard_is_ancestor(shard.shard, addr); } @@ -2214,7 +2240,7 @@ Ref Transaction::commit(Account& acc) { CHECK((const void*)&acc == (const void*)&account); // export all fields modified by the Transaction into original account // NB: this is the only method that modifies account - if (orig_addr_rewrite_set && new_split_depth >= 0 && acc.status == Account::acc_nonexist && + if (orig_addr_rewrite_set && new_split_depth >= 0 && acc.status != Account::acc_active && acc_status == Account::acc_active) { LOG(DEBUG) << "setting address rewriting info for newly-activated account " << acc.addr.to_hex() << " with split_depth=" << new_split_depth @@ -2243,9 +2269,7 @@ Ref Transaction::commit(Account& acc) { acc.tick = new_tick; acc.tock = new_tock; } else { - acc.tick = acc.tock = false; - acc.split_depth_set_ = false; - acc.created = true; + CHECK(acc.deactivate()); } end_lt = 0; acc.push_transaction(root, start_lt); diff --git a/crypto/block/transaction.h b/crypto/block/transaction.h index c1cfbc545..398e27319 100644 --- a/crypto/block/transaction.h +++ b/crypto/block/transaction.h @@ -213,17 +213,16 @@ struct Account { bool is_special{false}; bool tick{false}; bool tock{false}; - bool created{false}; bool split_depth_set_{false}; unsigned char split_depth_{0}; int verbosity{3 * 0}; ton::UnixTime now_{0}; ton::WorkchainId workchain{ton::workchainInvalid}; td::BitArray<32> addr_rewrite; // rewrite (anycast) data, split_depth bits - ton::StdSmcAddress addr; // rewritten address (by replacing a prefix of `addr_orig` with `addr_rewrite`) - ton::StdSmcAddress addr_orig; // address indicated in smart-contract data - Ref my_addr; // address as stored in the smart contract (MsgAddressInt) - Ref my_addr_exact; // exact address without anycast info + ton::StdSmcAddress addr; // rewritten address (by replacing a prefix of `addr_orig` with `addr_rewrite`); it is the key in ShardAccounts + ton::StdSmcAddress addr_orig; // address indicated in smart-contract data (must coincide with hash of StateInit) + Ref my_addr; // address as stored in the smart contract (MsgAddressInt); corresponds to `addr_orig` + anycast info + Ref my_addr_exact; // exact address without anycast info; corresponds to `addr` and has no anycast (rewrite) info ton::LogicalTime last_trans_end_lt_; ton::LogicalTime last_trans_lt_; ton::Bits256 last_trans_hash_; @@ -250,6 +249,7 @@ struct Account { bool set_address(ton::WorkchainId wc, td::ConstBitPtr new_addr); bool unpack(Ref account, Ref extra, ton::UnixTime now, bool special = false); bool init_new(ton::UnixTime now); + bool deactivate(); bool recompute_tmp_addr(Ref& tmp_addr, int split_depth, td::ConstBitPtr orig_addr_rewrite) const; td::RefInt256 compute_storage_fees(ton::UnixTime now, const std::vector& pricing) const; bool is_masterchain() const { @@ -268,6 +268,7 @@ struct Account { friend struct Transaction; bool set_split_depth(int split_depth); bool check_split_depth(int split_depth) const; + bool forget_split_depth(); bool init_rewrite_addr(int split_depth, td::ConstBitPtr orig_addr_rewrite); private: diff --git a/rldp2/CMakeLists.txt b/rldp2/CMakeLists.txt index f93f6e1e0..33ae5b672 100644 --- a/rldp2/CMakeLists.txt +++ b/rldp2/CMakeLists.txt @@ -51,7 +51,7 @@ target_include_directories(rldp PUBLIC ${OPENSSL_INCLUDE_DIR} ) if (GSL_FOUND) - target_link_libraries(rldp2 PRIVATE GSL::gsl) + target_link_libraries(rldp2 PRIVATE gsl) target_compile_definitions(rldp2 PRIVATE -DTON_HAVE_GSL=1) endif() target_link_libraries(rldp2 PUBLIC tdutils tdactor fec adnl tl_api) diff --git a/validator/impl/collator.cpp b/validator/impl/collator.cpp index 9ca4a6cc5..4c7db240e 100644 --- a/validator/impl/collator.cpp +++ b/validator/impl/collator.cpp @@ -1920,7 +1920,6 @@ std::unique_ptr Collator::make_account_from(td::ConstBitPtr addr } auto ptr = std::make_unique(workchain(), addr); if (account.is_null()) { - ptr->created = true; if (!ptr->init_new(now_)) { return nullptr; } @@ -2298,10 +2297,6 @@ Ref Collator::create_ordinary_transaction(Ref msg_root) { } register_new_msgs(*trans); update_max_lt(acc->last_trans_end_lt_); - // temporary patch to stop producing dangerous block - if (acc->status == block::Account::acc_nonexist) { - block_full_ = true; - } return trans_root; } @@ -2451,10 +2446,6 @@ int Collator::process_one_new_message(block::NewOutMsg msg, bool enqueue_only, R if (!insert_out_msg(cb.finalize())) { return -1; } - // 6.5. check for temporary patch can be left here - if (block_full_) { - return 3; - } // 7. check whether the block is full now if (!block_limit_status_->fits(block::ParamLimits::cl_normal)) { block_full_ = true; diff --git a/validator/impl/validate-query.cpp b/validator/impl/validate-query.cpp index fc90be1de..02a16f83a 100644 --- a/validator/impl/validate-query.cpp +++ b/validator/impl/validate-query.cpp @@ -4073,7 +4073,6 @@ std::unique_ptr ValidateQuery::make_account_from(td::ConstBitPtr Ref extra) { auto ptr = std::make_unique(workchain(), addr); if (account.is_null()) { - ptr->created = true; if (!ptr->init_new(now_)) { return nullptr; } @@ -4308,7 +4307,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT } } if (is_first && is_masterchain() && account.is_special && account.tick && - (tag != block::gen::TransactionDescr::trans_tick_tock || (td_cs.prefetch_ulong(4) & 1)) && !account.created) { + (tag != block::gen::TransactionDescr::trans_tick_tock || (td_cs.prefetch_ulong(4) & 1)) && account.orig_status == block::Account::acc_active) { return reject_query(PSTRING() << "transaction " << lt << " of account " << addr.to_hex() << " is the first transaction for this special tick account in this block, but the " "transaction is not a tick transaction");