mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	Merge branch 'testnet' into block-generation
This commit is contained in:
		
						commit
						d082ac36b0
					
				
					 261 changed files with 24449 additions and 1791 deletions
				
			
		|  | @ -227,6 +227,9 @@ bool AcceptBlockQuery::create_new_proof() { | |||
|   } | ||||
|   // 5. finish constructing Merkle proof from visited cells
 | ||||
|   auto proof = vm::MerkleProof::generate(block_root_, usage_tree.get()); | ||||
|   if (proof.is_null()) { | ||||
|     return fatal_error("cannot create proof"); | ||||
|   } | ||||
|   proof_roots_.push_back(proof); | ||||
|   // 6. extract some information from state update
 | ||||
|   state_old_hash_ = upd_cs.prefetch_ref(0)->get_hash(0).bits(); | ||||
|  |  | |||
|  | @ -103,19 +103,7 @@ class Collator final : public td::actor::Actor { | |||
|     return 2; | ||||
|   } | ||||
| 
 | ||||
|   static td::Result<std::unique_ptr<block::ConfigInfo>> | ||||
|                      impl_fetch_config_params(std::unique_ptr<block::ConfigInfo> config, | ||||
|                                               Ref<vm::Cell>* old_mparams, | ||||
|                                               std::vector<block::StoragePrices>* storage_prices, | ||||
|                                               block::StoragePhaseConfig* storage_phase_cfg, | ||||
|                                               td::BitArray<256>* rand_seed, | ||||
|                                               block::ComputePhaseConfig* compute_phase_cfg, | ||||
|                                               block::ActionPhaseConfig* action_phase_cfg, | ||||
|                                               td::RefInt256* masterchain_create_fee, | ||||
|                                               td::RefInt256* basechain_create_fee, | ||||
|                                               WorkchainId wc, UnixTime now); | ||||
| 
 | ||||
|   static td::Result<std::unique_ptr<block::Transaction>> | ||||
|   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, | ||||
|  | @ -290,7 +278,7 @@ class Collator final : public td::actor::Actor { | |||
|   td::Result<bool> register_shard_signatures_cell(Ref<vm::Cell> shard_blk_signatures); | ||||
|   td::Result<bool> register_shard_signatures(td::Slice shard_blk_signatures_boc); | ||||
|   void register_new_msg(block::NewOutMsg msg); | ||||
|   void register_new_msgs(block::Transaction& trans); | ||||
|   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(); | ||||
|  |  | |||
|  | @ -1594,90 +1594,19 @@ bool Collator::init_lt() { | |||
| } | ||||
| 
 | ||||
| bool Collator::fetch_config_params() { | ||||
|   auto res = impl_fetch_config_params(std::move(config_), &old_mparams_, &storage_prices_, &storage_phase_cfg_, | ||||
|                                       &rand_seed_, &compute_phase_cfg_, &action_phase_cfg_, &masterchain_create_fee_, | ||||
|                                       &basechain_create_fee_, workchain(), now_); | ||||
|   auto res = block::FetchConfigParams::fetch_config_params(*config_, | ||||
|                                       &old_mparams_, &storage_prices_, &storage_phase_cfg_, | ||||
|                                       &rand_seed_, &compute_phase_cfg_, &action_phase_cfg_, | ||||
|                                       &masterchain_create_fee_, &basechain_create_fee_, | ||||
|                                       workchain(), now_ | ||||
|                                      ); | ||||
|   if (res.is_error()) { | ||||
|     return fatal_error(res.move_as_error()); | ||||
|   } | ||||
|   config_ = res.move_as_ok(); | ||||
|   compute_phase_cfg_.libraries = std::make_unique<vm::Dictionary>(config_->get_libraries_root(), 256); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| td::Result<std::unique_ptr<block::ConfigInfo>> Collator::impl_fetch_config_params( | ||||
|     std::unique_ptr<block::ConfigInfo> config, Ref<vm::Cell>* old_mparams, | ||||
|     std::vector<block::StoragePrices>* storage_prices, block::StoragePhaseConfig* storage_phase_cfg, | ||||
|     td::BitArray<256>* rand_seed, block::ComputePhaseConfig* compute_phase_cfg, | ||||
|     block::ActionPhaseConfig* action_phase_cfg, td::RefInt256* masterchain_create_fee, | ||||
|     td::RefInt256* basechain_create_fee, WorkchainId wc, UnixTime now) { | ||||
|   *old_mparams = config->get_config_param(9); | ||||
|   { | ||||
|     auto res = config->get_storage_prices(); | ||||
|     if (res.is_error()) { | ||||
|       return res.move_as_error(); | ||||
|     } | ||||
|     *storage_prices = res.move_as_ok(); | ||||
|   } | ||||
|   { | ||||
|     // generate rand seed
 | ||||
|     prng::rand_gen().strong_rand_bytes(rand_seed->data(), 32); | ||||
|     LOG(DEBUG) << "block random seed set to " << rand_seed->to_hex(); | ||||
|   } | ||||
|   TRY_RESULT(size_limits, config->get_size_limits_config()); | ||||
|   { | ||||
|     // compute compute_phase_cfg / storage_phase_cfg
 | ||||
|     auto cell = config->get_config_param(wc == ton::masterchainId ? 20 : 21); | ||||
|     if (cell.is_null()) { | ||||
|       return td::Status::Error(-668, "cannot fetch current gas prices and limits from masterchain configuration"); | ||||
|     } | ||||
|     if (!compute_phase_cfg->parse_GasLimitsPrices(std::move(cell), storage_phase_cfg->freeze_due_limit, | ||||
|                                                   storage_phase_cfg->delete_due_limit)) { | ||||
|       return td::Status::Error(-668, "cannot unpack current gas prices and limits from masterchain configuration"); | ||||
|     } | ||||
|     compute_phase_cfg->block_rand_seed = *rand_seed; | ||||
|     compute_phase_cfg->libraries = std::make_unique<vm::Dictionary>(config->get_libraries_root(), 256); | ||||
|     compute_phase_cfg->max_vm_data_depth = size_limits.max_vm_data_depth; | ||||
|     compute_phase_cfg->global_config = config->get_root_cell(); | ||||
|     compute_phase_cfg->suspended_addresses = config->get_suspended_addresses(now); | ||||
|   } | ||||
|   { | ||||
|     // compute action_phase_cfg
 | ||||
|     block::gen::MsgForwardPrices::Record rec; | ||||
|     auto cell = config->get_config_param(24); | ||||
|     if (cell.is_null() || !tlb::unpack_cell(std::move(cell), rec)) { | ||||
|       return td::Status::Error(-668, "cannot fetch masterchain message transfer prices from masterchain configuration"); | ||||
|     } | ||||
|     action_phase_cfg->fwd_mc = | ||||
|         block::MsgPrices{rec.lump_price,           rec.bit_price,          rec.cell_price, rec.ihr_price_factor, | ||||
|                          (unsigned)rec.first_frac, (unsigned)rec.next_frac}; | ||||
|     cell = config->get_config_param(25); | ||||
|     if (cell.is_null() || !tlb::unpack_cell(std::move(cell), rec)) { | ||||
|       return td::Status::Error(-668, "cannot fetch standard message transfer prices from masterchain configuration"); | ||||
|     } | ||||
|     action_phase_cfg->fwd_std = | ||||
|         block::MsgPrices{rec.lump_price,           rec.bit_price,          rec.cell_price, rec.ihr_price_factor, | ||||
|                          (unsigned)rec.first_frac, (unsigned)rec.next_frac}; | ||||
|     action_phase_cfg->workchains = &config->get_workchain_list(); | ||||
|     action_phase_cfg->bounce_msg_body = (config->has_capability(ton::capBounceMsgBody) ? 256 : 0); | ||||
|     action_phase_cfg->size_limits = size_limits; | ||||
|   } | ||||
|   { | ||||
|     // fetch block_grams_created
 | ||||
|     auto cell = config->get_config_param(14); | ||||
|     if (cell.is_null()) { | ||||
|       *basechain_create_fee = *masterchain_create_fee = td::zero_refint(); | ||||
|     } else { | ||||
|       block::gen::BlockCreateFees::Record create_fees; | ||||
|       if (!(tlb::unpack_cell(cell, create_fees) && | ||||
|             block::tlb::t_Grams.as_integer_to(create_fees.masterchain_block_fee, *masterchain_create_fee) && | ||||
|             block::tlb::t_Grams.as_integer_to(create_fees.basechain_block_fee, *basechain_create_fee))) { | ||||
|         return td::Status::Error(-668, "cannot unpack BlockCreateFees from configuration parameter #14"); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   return std::move(config); | ||||
| } | ||||
| 
 | ||||
| bool Collator::compute_minted_amount(block::CurrencyCollection& to_mint) { | ||||
|   if (!is_masterchain()) { | ||||
|     return to_mint.set_zero(); | ||||
|  | @ -2200,8 +2129,8 @@ bool Collator::create_ticktock_transaction(const ton::StdSmcAddress& smc_addr, t | |||
|                                                    << "last transaction time in the state of account " << workchain() | ||||
|                                                    << ":" << smc_addr.to_hex() << " is too large")); | ||||
|   } | ||||
|   std::unique_ptr<block::Transaction> trans = std::make_unique<block::Transaction>( | ||||
|       *acc, mask == 2 ? block::Transaction::tr_tick : block::Transaction::tr_tock, req_start_lt, now_); | ||||
|   std::unique_ptr<block::transaction::Transaction> trans = std::make_unique<block::transaction::Transaction>( | ||||
|       *acc, mask == 2 ? block::transaction::Transaction::tr_tick : block::transaction::Transaction::tr_tock, req_start_lt, now_); | ||||
|   if (!trans->prepare_storage_phase(storage_phase_cfg_, true)) { | ||||
|     return fatal_error(td::Status::Error( | ||||
|         -666, std::string{"cannot create storage phase of a new transaction for smart contract "} + smc_addr.to_hex())); | ||||
|  | @ -2291,7 +2220,7 @@ Ref<vm::Cell> Collator::create_ordinary_transaction(Ref<vm::Cell> msg_root) { | |||
|     fatal_error(std::move(error)); | ||||
|     return {}; | ||||
|   } | ||||
|   std::unique_ptr<block::Transaction> trans = res.move_as_ok(); | ||||
|   std::unique_ptr<block::transaction::Transaction> trans = res.move_as_ok(); | ||||
| 
 | ||||
|   if (!trans->update_limits(*block_limit_status_)) { | ||||
|     fatal_error("cannot update block limit status to include the new transaction"); | ||||
|  | @ -2310,10 +2239,13 @@ Ref<vm::Cell> Collator::create_ordinary_transaction(Ref<vm::Cell> msg_root) { | |||
| 
 | ||||
| // If td::status::error_code == 669 - Fatal Error block can not be produced
 | ||||
| // if td::status::error_code == 701 - Transaction can not be included into block, but it's ok (external or too early internal)
 | ||||
| td::Result<std::unique_ptr<block::Transaction>> Collator::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) { | ||||
| td::Result<std::unique_ptr<block::transaction::Transaction>> Collator::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) { | ||||
|   if (acc->last_trans_end_lt_ >= lt && acc->transactions.empty()) { | ||||
|     return td::Status::Error(-669, PSTRING() << "last transaction time in the state of account " << acc->workchain | ||||
|                                              << ":" << acc->addr.to_hex() << " is too large"); | ||||
|  | @ -2324,8 +2256,8 @@ td::Result<std::unique_ptr<block::Transaction>> Collator::impl_create_ordinary_t | |||
|     trans_min_lt = std::max(trans_min_lt, after_lt); | ||||
|   } | ||||
| 
 | ||||
|   std::unique_ptr<block::Transaction> trans = | ||||
|       std::make_unique<block::Transaction>(*acc, block::Transaction::tr_ord, trans_min_lt + 1, utime, msg_root); | ||||
|   std::unique_ptr<block::transaction::Transaction> trans = | ||||
|       std::make_unique<block::transaction::Transaction>(*acc, block::transaction::Transaction::tr_ord, trans_min_lt + 1, utime, msg_root); | ||||
|   bool ihr_delivered = false;  // FIXME
 | ||||
|   if (!trans->unpack_input_msg(ihr_delivered, action_phase_cfg)) { | ||||
|     if (external) { | ||||
|  | @ -2375,7 +2307,7 @@ td::Result<std::unique_ptr<block::Transaction>> Collator::impl_create_ordinary_t | |||
|     return td::Status::Error( | ||||
|         -669, "cannot create action phase of a new transaction for smart contract "s + acc->addr.to_hex()); | ||||
|   } | ||||
|   if (trans->bounce_enabled && (!trans->compute_phase->success || trans->action_phase->state_size_too_big) && | ||||
|   if (trans->bounce_enabled && (!trans->compute_phase->success || trans->action_phase->state_exceeds_limits) && | ||||
|       !trans->prepare_bounce_phase(*action_phase_cfg)) { | ||||
|     return td::Status::Error( | ||||
|         -669, "cannot create bounce phase of a new transaction for smart contract "s + acc->addr.to_hex()); | ||||
|  | @ -3088,7 +3020,7 @@ void Collator::register_new_msg(block::NewOutMsg new_msg) { | |||
|   new_msgs.push(std::move(new_msg)); | ||||
| } | ||||
| 
 | ||||
| void Collator::register_new_msgs(block::Transaction& trans) { | ||||
| void Collator::register_new_msgs(block::transaction::Transaction& trans) { | ||||
|   CHECK(trans.root.not_null()); | ||||
|   for (unsigned i = 0; i < trans.out_msgs.size(); i++) { | ||||
|     register_new_msg(trans.extract_out_msg_ext(i)); | ||||
|  | @ -3755,6 +3687,9 @@ bool Collator::create_shard_state() { | |||
|   } | ||||
|   LOG(INFO) << "creating Merkle update for the ShardState"; | ||||
|   state_update = vm::MerkleUpdate::generate(prev_state_root_, state_root, state_usage_tree_.get()); | ||||
|   if (state_update.is_null()) { | ||||
|     return fatal_error("cannot create Merkle update for ShardState"); | ||||
|   } | ||||
|   if (verbosity > 2) { | ||||
|     std::cerr << "Merkle Update for ShardState: "; | ||||
|     vm::CellSlice cs{vm::NoVm{}, state_update}; | ||||
|  | @ -4074,7 +4009,11 @@ bool Collator::create_collated_data() { | |||
|   } | ||||
|   // 4. Proofs for message queues
 | ||||
|   for (vm::MerkleProofBuilder &mpb : neighbor_proof_builders_) { | ||||
|     Ref<vm::Cell> proof = mpb.extract_proof(); | ||||
|     auto r_proof = mpb.extract_proof(); | ||||
|     if (r_proof.is_error()) { | ||||
|       return fatal_error(r_proof.move_as_error_prefix("cannot generate Merkle proof for neighbor: ")); | ||||
|     } | ||||
|     Ref<vm::Cell> proof = r_proof.move_as_ok(); | ||||
|     if (proof.is_null()) { | ||||
|       return fatal_error("cannot generate Merkle proof for neighbor"); | ||||
|     } | ||||
|  |  | |||
|  | @ -143,16 +143,17 @@ td::Status ExtMessageQ::run_message_on_account(ton::WorkchainId wc, | |||
|    block::ActionPhaseConfig action_phase_cfg_; | ||||
|    td::RefInt256 masterchain_create_fee, basechain_create_fee; | ||||
| 
 | ||||
|    auto fetch_res = Collator::impl_fetch_config_params(std::move(config), &old_mparams, | ||||
|                                                  &storage_prices_, &storage_phase_cfg_, | ||||
|                                                  &rand_seed_, &compute_phase_cfg_, | ||||
|                                                  &action_phase_cfg_, &masterchain_create_fee, | ||||
|                                                  &basechain_create_fee, wc, utime); | ||||
|    auto fetch_res = block::FetchConfigParams::fetch_config_params(*config, &old_mparams, | ||||
|                                                                   &storage_prices_, &storage_phase_cfg_, | ||||
|                                                                   &rand_seed_, &compute_phase_cfg_, | ||||
|                                                                   &action_phase_cfg_, &masterchain_create_fee, | ||||
|                                                                   &basechain_create_fee, wc, utime); | ||||
|    if(fetch_res.is_error()) { | ||||
|      auto error = fetch_res.move_as_error(); | ||||
|      LOG(DEBUG) << "Cannot fetch config params: " << error.message(); | ||||
|      return error.move_as_error_prefix("Cannot fetch config params: "); | ||||
|    } | ||||
|    compute_phase_cfg_.libraries = std::make_unique<vm::Dictionary>(config->get_libraries_root(), 256); | ||||
|    compute_phase_cfg_.with_vm_log = true; | ||||
| 
 | ||||
|    auto res = Collator::impl_create_ordinary_transaction(msg_root, acc, utime, lt, | ||||
|  | @ -164,7 +165,7 @@ td::Status ExtMessageQ::run_message_on_account(ton::WorkchainId wc, | |||
|      LOG(DEBUG) << "Cannot run message on account: " << error.message(); | ||||
|      return error.move_as_error_prefix("Cannot run message on account: "); | ||||
|    } | ||||
|    std::unique_ptr<block::Transaction> trans = res.move_as_ok(); | ||||
|    std::unique_ptr<block::transaction::Transaction> trans = res.move_as_ok(); | ||||
| 
 | ||||
|    auto trans_root = trans->commit(*acc); | ||||
|    if (trans_root.is_null()) { | ||||
|  |  | |||
|  | @ -182,6 +182,11 @@ void LiteQuery::start_up() { | |||
|                                                 (q.mode_ & 128) ? q.after_->account_ : td::Bits256::zero(), | ||||
|                                                 static_cast<LogicalTime>((q.mode_ & 128) ? (q.after_->lt_) : 0)); | ||||
|           }, | ||||
|           [&](lite_api::liteServer_listBlockTransactionsExt& q) { | ||||
|             this->perform_listBlockTransactionsExt(ton::create_block_id(q.id_), q.mode_, q.count_, | ||||
|                                                 (q.mode_ & 128) ? q.after_->account_ : td::Bits256::zero(), | ||||
|                                                 static_cast<LogicalTime>((q.mode_ & 128) ? (q.after_->lt_) : 0)); | ||||
|           }, | ||||
|           [&](lite_api::liteServer_getConfigParams& q) { | ||||
|             this->perform_getConfigParams(ton::create_block_id(q.id_), (q.mode_ & 0xffff) | 0x10000, q.param_list_); | ||||
|           }, | ||||
|  | @ -509,7 +514,7 @@ void LiteQuery::get_block_handle_checked(BlockIdExt blkid, td::Promise<ConstBloc | |||
|           if (handle->is_applied()) { | ||||
|             promise.set_result(std::move(handle)); | ||||
|           } else { | ||||
|             promise.set_error(td::Status::Error("block is not applied")); | ||||
|             promise.set_error(td::Status::Error(ErrorCode::notready, "block is not applied")); | ||||
|           } | ||||
|         } | ||||
|       }); | ||||
|  | @ -1050,9 +1055,9 @@ bool LiteQuery::make_state_root_proof(Ref<vm::Cell>& proof, Ref<vm::Cell> state_ | |||
|         && upd_cs.size_ext() == 0x20228)) { | ||||
|     return fatal_error("invalid Merkle update in block"); | ||||
|   } | ||||
|   auto upd_hash = upd_cs.prefetch_ref(1)->get_hash(0).bits(); | ||||
|   auto state_hash = state_root->get_hash().bits(); | ||||
|   if (upd_hash.compare(state_hash, 256)) { | ||||
|   auto upd_hash = upd_cs.prefetch_ref(1)->get_hash(0); | ||||
|   auto state_hash = state_root->get_hash(); | ||||
|   if (upd_hash != state_hash) { | ||||
|     return fatal_error("cannot construct Merkle proof for given masterchain state because of hash mismatch"); | ||||
|   } | ||||
|   if (!pb.extract_proof_to(proof)) { | ||||
|  | @ -1168,7 +1173,7 @@ void LiteQuery::continue_getAccountState() { | |||
| 
 | ||||
| void LiteQuery::finish_getAccountState(td::BufferSlice shard_proof) { | ||||
|   LOG(INFO) << "completing getAccountState() query"; | ||||
|   Ref<vm::Cell> proof1; | ||||
|   Ref<vm::Cell> proof1, proof2; | ||||
|   if (!make_state_root_proof(proof1)) { | ||||
|     return; | ||||
|   } | ||||
|  | @ -1197,7 +1202,11 @@ void LiteQuery::finish_getAccountState(td::BufferSlice shard_proof) { | |||
|   if (acc_csr.not_null()) { | ||||
|     acc_root = acc_csr->prefetch_ref(); | ||||
|   } | ||||
|   auto proof = vm::std_boc_serialize_multi({std::move(proof1), pb.extract_proof()}); | ||||
|   if (!pb.extract_proof_to(proof2)) { | ||||
|     fatal_error("unknown error creating Merkle proof"); | ||||
|     return; | ||||
|   } | ||||
|   auto proof = vm::std_boc_serialize_multi({std::move(proof1), std::move(proof2)}); | ||||
|   pb.clear(); | ||||
|   if (proof.is_error()) { | ||||
|     fatal_error(proof.move_as_error()); | ||||
|  | @ -1221,7 +1230,10 @@ void LiteQuery::finish_getAccountState(td::BufferSlice shard_proof) { | |||
|         fatal_error(S.move_as_error_prefix("Failed to load account: ")); | ||||
|         return; | ||||
|       } | ||||
|       acc_root = mpb.extract_proof(); | ||||
|       if (!mpb.extract_proof_to(acc_root)) { | ||||
|         fatal_error("unknown error creating Merkle proof"); | ||||
|         return; | ||||
|       } | ||||
|     } | ||||
|     auto res = vm::std_boc_serialize(std::move(acc_root)); | ||||
|     if (res.is_error()) { | ||||
|  | @ -1283,10 +1295,20 @@ void LiteQuery::finish_runSmcMethod(td::BufferSlice shard_proof, td::BufferSlice | |||
|         balance.validate_unpack(store.balance) && store.state->prefetch_ulong(1) == 1 && | ||||
|         store.state.write().advance(1) && tlb::csr_unpack(std::move(store.state), state_init))) { | ||||
|     LOG(INFO) << "error unpacking account state, or account is frozen or uninitialized"; | ||||
|     td::Result<td::BufferSlice> proof_boc; | ||||
|     if (mode & 2) { | ||||
|       proof_boc = pb.extract_proof_boc(); | ||||
|       if (proof_boc.is_error()) { | ||||
|         fatal_error(proof_boc.move_as_error()); | ||||
|         return; | ||||
|       } | ||||
|     } else { | ||||
|       proof_boc = td::BufferSlice(); | ||||
|     } | ||||
|     auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_runMethodResult>( | ||||
|         mode, ton::create_tl_lite_block_id(base_blk_id_), ton::create_tl_lite_block_id(blk_id_), std::move(shard_proof), | ||||
|         std::move(state_proof), mode & 2 ? pb.extract_proof_boc().move_as_ok() : td::BufferSlice(), td::BufferSlice(), | ||||
|         td::BufferSlice(), -0x100, td::BufferSlice()); | ||||
|         std::move(state_proof), proof_boc.move_as_ok(), td::BufferSlice(), td::BufferSlice(), -0x100, | ||||
|         td::BufferSlice()); | ||||
|     finish_query(std::move(b)); | ||||
|     return; | ||||
|   } | ||||
|  | @ -1340,10 +1362,20 @@ void LiteQuery::finish_runSmcMethod(td::BufferSlice shard_proof, td::BufferSlice | |||
|     } | ||||
|     result = res.move_as_ok(); | ||||
|   } | ||||
|   td::Result<td::BufferSlice> proof_boc; | ||||
|   if (mode & 2) { | ||||
|     proof_boc = pb.extract_proof_boc(); | ||||
|     if (proof_boc.is_error()) { | ||||
|       fatal_error(proof_boc.move_as_error()); | ||||
|       return; | ||||
|     } | ||||
|   } else { | ||||
|     proof_boc = td::BufferSlice(); | ||||
|   } | ||||
|   auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_runMethodResult>( | ||||
|       mode, ton::create_tl_lite_block_id(base_blk_id_), ton::create_tl_lite_block_id(blk_id_), std::move(shard_proof), | ||||
|       std::move(state_proof), mode & 2 ? pb.extract_proof_boc().move_as_ok() : td::BufferSlice(), std::move(c7_info), | ||||
|       td::BufferSlice(), exit_code, std::move(result)); | ||||
|       std::move(state_proof), proof_boc.move_as_ok(), std::move(c7_info), td::BufferSlice(), exit_code, | ||||
|       std::move(result)); | ||||
|   finish_query(std::move(b)); | ||||
| } | ||||
| 
 | ||||
|  | @ -1471,7 +1503,7 @@ void LiteQuery::continue_getTransactions(unsigned remaining, bool exact) { | |||
|         } else { | ||||
|           auto handle = res.move_as_ok(); | ||||
|           if (!handle->is_applied()) { | ||||
|             td::actor::send_closure(Self, &LiteQuery::abort_getTransactions, td::Status::Error("block is not applied"), | ||||
|             td::actor::send_closure(Self, &LiteQuery::abort_getTransactions, td::Status::Error(ErrorCode::notready, "block is not applied"), | ||||
|                                     ton::BlockIdExt{}); | ||||
|             return; | ||||
|           } | ||||
|  | @ -1801,7 +1833,7 @@ void LiteQuery::perform_lookupBlock(BlockId blkid, int mode, LogicalTime lt, Uni | |||
|         } else { | ||||
|           auto handle = res.move_as_ok(); | ||||
|           if (!handle->is_applied()) { | ||||
|             td::actor::send_closure(Self, &LiteQuery::abort_query, td::Status::Error("block is not applied")); | ||||
|             td::actor::send_closure(Self, &LiteQuery::abort_query, td::Status::Error(ErrorCode::notready, "block is not applied")); | ||||
|             return; | ||||
|           } | ||||
|           LOG(DEBUG) << "requesting data for block " << handle->id().to_str(); | ||||
|  | @ -1937,6 +1969,118 @@ void LiteQuery::finish_listBlockTransactions(int mode, int req_count) { | |||
|   finish_query(std::move(b)); | ||||
| } | ||||
| 
 | ||||
| void LiteQuery::perform_listBlockTransactionsExt(BlockIdExt blkid, int mode, int count, Bits256 account, LogicalTime lt) { | ||||
|   LOG(INFO) << "started a listBlockTransactionsExt(" << blkid.to_str() << ", " << mode << ", " << count << ", " | ||||
|             << account.to_hex() << ", " << lt << ") liteserver query"; | ||||
|   base_blk_id_ = blkid; | ||||
|   acc_addr_ = account; | ||||
|   trans_lt_ = lt; | ||||
|   set_continuation([this, mode, count]() -> void { finish_listBlockTransactionsExt(mode, count); }); | ||||
|   request_block_data(blkid); | ||||
| } | ||||
| 
 | ||||
| void LiteQuery::finish_listBlockTransactionsExt(int mode, int req_count) { | ||||
|   LOG(INFO) << "completing a listBlockTransactionsExt(" << base_blk_id_.to_str() << ", " << mode << ", " << req_count | ||||
|             << ", " << acc_addr_.to_hex() << ", " << trans_lt_ << ") liteserver query"; | ||||
|   constexpr int max_answer_transactions = 256; | ||||
|   CHECK(block_.not_null()); | ||||
|   auto block_root = block_->root_cell(); | ||||
|   CHECK(block_root.not_null()); | ||||
|   RootHash rhash{block_root->get_hash().bits()}; | ||||
|   CHECK(rhash == base_blk_id_.root_hash); | ||||
|   vm::MerkleProofBuilder pb; | ||||
|   auto virt_root = block_root; | ||||
|   if (mode & 32) { | ||||
|     // proof requested
 | ||||
|     virt_root = pb.init(std::move(virt_root)); | ||||
|   } | ||||
|   if ((mode & 192) == 64) {  // reverse order, no starting point
 | ||||
|     acc_addr_.set_ones(); | ||||
|     trans_lt_ = ~0ULL; | ||||
|   } | ||||
|   std::vector<Ref<vm::Cell>> trans_roots; | ||||
|   bool eof = false; | ||||
|   ton::LogicalTime reverse = (mode & 64) ? ~0ULL : 0; | ||||
|   try { | ||||
|     block::gen::Block::Record blk; | ||||
|     block::gen::BlockExtra::Record extra; | ||||
|     if (!(tlb::unpack_cell(virt_root, blk) && tlb::unpack_cell(std::move(blk.extra), extra))) { | ||||
|       fatal_error("cannot find account transaction data in block "s + base_blk_id_.to_str()); | ||||
|       return; | ||||
|     } | ||||
|     vm::AugmentedDictionary acc_dict{vm::load_cell_slice_ref(extra.account_blocks), 256, | ||||
|                                      block::tlb::aug_ShardAccountBlocks}; | ||||
|     int count = 0; | ||||
|     bool allow_same = true; | ||||
|     td::Bits256 cur_addr = acc_addr_; | ||||
|     while (!eof && count < req_count && count < max_answer_transactions) { | ||||
|       Ref<vm::CellSlice> value; | ||||
|       try { | ||||
|         value = acc_dict.extract_value( | ||||
|             acc_dict.vm::DictionaryFixed::lookup_nearest_key(cur_addr.bits(), 256, !reverse, allow_same)); | ||||
|       } catch (vm::VmError err) { | ||||
|         fatal_error("error while traversing account block dictionary: "s + err.get_msg()); | ||||
|         return; | ||||
|       } | ||||
|       if (value.is_null()) { | ||||
|         eof = true; | ||||
|         break; | ||||
|       } | ||||
|       allow_same = false; | ||||
|       if (cur_addr != acc_addr_) { | ||||
|         trans_lt_ = reverse; | ||||
|       } | ||||
|       block::gen::AccountBlock::Record acc_blk; | ||||
|       if (!(tlb::csr_unpack(std::move(value), acc_blk) && acc_blk.account_addr == cur_addr)) { | ||||
|         fatal_error("invalid AccountBlock for account "s + cur_addr.to_hex()); | ||||
|         return; | ||||
|       } | ||||
|       vm::AugmentedDictionary trans_dict{vm::DictNonEmpty(), std::move(acc_blk.transactions), 64, | ||||
|                                          block::tlb::aug_AccountTransactions}; | ||||
|       td::BitArray<64> cur_trans{(long long)trans_lt_}; | ||||
|       while (count < req_count && count < max_answer_transactions) { | ||||
|         Ref<vm::Cell> tvalue; | ||||
|         try { | ||||
|           tvalue = trans_dict.extract_value_ref( | ||||
|               trans_dict.vm::DictionaryFixed::lookup_nearest_key(cur_trans.bits(), 64, !reverse)); | ||||
|         } catch (vm::VmError err) { | ||||
|           fatal_error("error while traversing transaction dictionary of an AccountBlock: "s + err.get_msg()); | ||||
|           return; | ||||
|         } | ||||
|         if (tvalue.is_null()) { | ||||
|           trans_lt_ = reverse; | ||||
|           break; | ||||
|         } | ||||
|         trans_roots.push_back(std::move(tvalue)); | ||||
|         ++count; | ||||
|       } | ||||
|     } | ||||
|   } catch (vm::VmError err) { | ||||
|     fatal_error("error while parsing AccountBlocks of block "s + base_blk_id_.to_str() + " : " + err.get_msg()); | ||||
|     return; | ||||
|   } | ||||
|   td::BufferSlice proof_data; | ||||
|   if (mode & 32) { | ||||
|     // create proof
 | ||||
|     auto proof_boc = pb.extract_proof_boc(); | ||||
|     if (proof_boc.is_error()) { | ||||
|       fatal_error(proof_boc.move_as_error()); | ||||
|       return; | ||||
|     } | ||||
|     proof_data = proof_boc.move_as_ok(); | ||||
|   } | ||||
|   auto res = vm::std_boc_serialize_multi(std::move(trans_roots)); | ||||
|   if (res.is_error()) { | ||||
|     fatal_error(res.move_as_error()); | ||||
|     return; | ||||
|   } | ||||
|    | ||||
|   auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_blockTransactionsExt>( | ||||
|       ton::create_tl_lite_block_id(base_blk_id_), req_count, !eof, res.move_as_ok(), std::move(proof_data)); | ||||
|   LOG(INFO) << "listBlockTransactionsExt() query completed"; | ||||
|   finish_query(std::move(b)); | ||||
| } | ||||
| 
 | ||||
| void LiteQuery::perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to, int mode) { | ||||
|   if (!(mode & 1)) { | ||||
|     to.invalidate_clear(); | ||||
|  |  | |||
|  | @ -133,6 +133,8 @@ class LiteQuery : public td::actor::Actor { | |||
|   void perform_lookupBlock(BlockId blkid, int mode, LogicalTime lt, UnixTime utime); | ||||
|   void perform_listBlockTransactions(BlockIdExt blkid, int mode, int count, Bits256 account, LogicalTime lt); | ||||
|   void finish_listBlockTransactions(int mode, int count); | ||||
|   void perform_listBlockTransactionsExt(BlockIdExt blkid, int mode, int count, Bits256 account, LogicalTime lt); | ||||
|   void finish_listBlockTransactionsExt(int mode, int count); | ||||
|   void perform_getBlockProof(BlockIdExt from, BlockIdExt to, int mode); | ||||
|   void continue_getBlockProof(BlockIdExt from, BlockIdExt to, int mode, BlockIdExt baseblk, | ||||
|                               Ref<MasterchainStateQ> state); | ||||
|  |  | |||
|  | @ -129,7 +129,7 @@ td::Result<tl_object_ptr<ton_api::tonNode_outMsgQueueProof>> OutMsgQueueProof::s | |||
|   } | ||||
|   dfs(queue->get_root_cell()); | ||||
| 
 | ||||
|   TRY_RESULT(queue_proof, vm::std_boc_serialize(mpb.extract_proof())); | ||||
|   TRY_RESULT(queue_proof, mpb.extract_proof_boc()); | ||||
|   td::BufferSlice block_state_proof; | ||||
|   if (block_id.seqno() != 0) { | ||||
|     TRY_RESULT(proof, create_block_state_proof(std::move(block_root))); | ||||
|  |  | |||
|  | @ -171,7 +171,7 @@ td::Result<td::Ref<vm::Cell>> create_block_state_proof(td::Ref<vm::Cell> root) { | |||
|   if (!tlb::unpack_cell(mpb.root(), block) || block.state_update->load_cell().is_error()) { | ||||
|     return td::Status::Error("invalid block"); | ||||
|   } | ||||
|   Ref<vm::Cell> proof = mpb.extract_proof(); | ||||
|   TRY_RESULT(proof, mpb.extract_proof()); | ||||
|   if (proof.is_null()) { | ||||
|     return td::Status::Error("failed to create proof"); | ||||
|   } | ||||
|  |  | |||
|  | @ -4441,7 +4441,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT | |||
|                                   << account.total_state->get_hash().to_hex()); | ||||
|   } | ||||
|   // some type-specific checks
 | ||||
|   int trans_type = block::Transaction::tr_none; | ||||
|   int trans_type = block::transaction::Transaction::tr_none; | ||||
|   switch (tag) { | ||||
|     case block::gen::TransactionDescr::trans_ord: { | ||||
|       if (!block_limit_status_->fits(block::ParamLimits::cl_medium)) { | ||||
|  | @ -4451,7 +4451,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT | |||
|                                       << "lt_delta=" << block_limit_status_->cur_lt - block_limits_->start_lt | ||||
|                                       << "(limit=" << block_limits_->lt_delta.hard() << ")"); | ||||
|       } | ||||
|       trans_type = block::Transaction::tr_ord; | ||||
|       trans_type = block::transaction::Transaction::tr_ord; | ||||
|       if (in_msg_root.is_null()) { | ||||
|         return reject_query(PSTRING() << "ordinary transaction " << lt << " of account " << addr.to_hex() | ||||
|                                       << " has no inbound message"); | ||||
|  | @ -4460,7 +4460,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT | |||
|       break; | ||||
|     } | ||||
|     case block::gen::TransactionDescr::trans_storage: { | ||||
|       trans_type = block::Transaction::tr_storage; | ||||
|       trans_type = block::transaction::Transaction::tr_storage; | ||||
|       if (in_msg_root.not_null()) { | ||||
|         return reject_query(PSTRING() << "storage transaction " << lt << " of account " << addr.to_hex() | ||||
|                                       << " has an inbound message"); | ||||
|  | @ -4476,7 +4476,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT | |||
|     } | ||||
|     case block::gen::TransactionDescr::trans_tick_tock: { | ||||
|       bool is_tock = (td_cs.prefetch_ulong(4) & 1); | ||||
|       trans_type = is_tock ? block::Transaction::tr_tock : block::Transaction::tr_tick; | ||||
|       trans_type = is_tock ? block::transaction::Transaction::tr_tock : block::transaction::Transaction::tr_tick; | ||||
|       if (in_msg_root.not_null()) { | ||||
|         return reject_query(PSTRING() << (is_tock ? "tock" : "tick") << " transaction " << lt << " of account " | ||||
|                                       << addr.to_hex() << " has an inbound message"); | ||||
|  | @ -4484,7 +4484,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT | |||
|       break; | ||||
|     } | ||||
|     case block::gen::TransactionDescr::trans_merge_prepare: { | ||||
|       trans_type = block::Transaction::tr_merge_prepare; | ||||
|       trans_type = block::transaction::Transaction::tr_merge_prepare; | ||||
|       if (in_msg_root.not_null()) { | ||||
|         return reject_query(PSTRING() << "merge prepare transaction " << lt << " of account " << addr.to_hex() | ||||
|                                       << " has an inbound message"); | ||||
|  | @ -4499,7 +4499,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT | |||
|       break; | ||||
|     } | ||||
|     case block::gen::TransactionDescr::trans_merge_install: { | ||||
|       trans_type = block::Transaction::tr_merge_install; | ||||
|       trans_type = block::transaction::Transaction::tr_merge_install; | ||||
|       if (in_msg_root.is_null()) { | ||||
|         return reject_query(PSTRING() << "merge install transaction " << lt << " of account " << addr.to_hex() | ||||
|                                       << " has no inbound message"); | ||||
|  | @ -4511,7 +4511,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT | |||
|       break; | ||||
|     } | ||||
|     case block::gen::TransactionDescr::trans_split_prepare: { | ||||
|       trans_type = block::Transaction::tr_split_prepare; | ||||
|       trans_type = block::transaction::Transaction::tr_split_prepare; | ||||
|       if (in_msg_root.not_null()) { | ||||
|         return reject_query(PSTRING() << "split prepare transaction " << lt << " of account " << addr.to_hex() | ||||
|                                       << " has an inbound message"); | ||||
|  | @ -4526,7 +4526,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT | |||
|       break; | ||||
|     } | ||||
|     case block::gen::TransactionDescr::trans_split_install: { | ||||
|       trans_type = block::Transaction::tr_split_install; | ||||
|       trans_type = block::transaction::Transaction::tr_split_install; | ||||
|       if (in_msg_root.is_null()) { | ||||
|         return reject_query(PSTRING() << "split install transaction " << lt << " of account " << addr.to_hex() | ||||
|                                       << " has no inbound message"); | ||||
|  | @ -4541,8 +4541,8 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT | |||
|   // check transaction computation by re-doing it
 | ||||
|   // similar to Collator::create_ordinary_transaction() and Collator::create_ticktock_transaction()
 | ||||
|   // ....
 | ||||
|   std::unique_ptr<block::Transaction> trs = | ||||
|       std::make_unique<block::Transaction>(account, trans_type, lt, now_, in_msg_root); | ||||
|   std::unique_ptr<block::transaction::Transaction> trs = | ||||
|       std::make_unique<block::transaction::Transaction>(account, trans_type, lt, now_, in_msg_root); | ||||
|   if (in_msg_root.not_null()) { | ||||
|     if (!trs->unpack_input_msg(ihr_delivered, &action_phase_cfg_)) { | ||||
|       // inbound external message was not accepted
 | ||||
|  | @ -4588,7 +4588,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT | |||
|     return reject_query(PSTRING() << "cannot re-create action phase of transaction " << lt << " for smart contract " | ||||
|                                   << addr.to_hex()); | ||||
|   } | ||||
|   if (trs->bounce_enabled && (!trs->compute_phase->success || trs->action_phase->state_size_too_big) && | ||||
|   if (trs->bounce_enabled && (!trs->compute_phase->success || trs->action_phase->state_exceeds_limits) && | ||||
|       !trs->prepare_bounce_phase(action_phase_cfg_)) { | ||||
|     return reject_query(PSTRING() << "cannot re-create bounce phase of  transaction " << lt << " for smart contract " | ||||
|                                   << addr.to_hex()); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue