mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Add checks for external messages
This commit is contained in:
parent
69d0472510
commit
3384d204d2
11 changed files with 396 additions and 119 deletions
|
@ -1556,68 +1556,92 @@ bool Collator::init_lt() {
|
|||
}
|
||||
|
||||
bool Collator::fetch_config_params() {
|
||||
old_mparams_ = config_->get_config_param(9);
|
||||
{
|
||||
auto res = config_->get_storage_prices();
|
||||
if (res.is_error()) {
|
||||
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()
|
||||
);
|
||||
if (res.is_error()) {
|
||||
return fatal_error(res.move_as_error());
|
||||
}
|
||||
config_ = res.move_as_ok();
|
||||
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) {
|
||||
*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();
|
||||
*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();
|
||||
prng::rand_gen().strong_rand_bytes(rand_seed->data(), 32);
|
||||
LOG(DEBUG) << "block random seed set to " << rand_seed->to_hex();
|
||||
}
|
||||
{
|
||||
// compute compute_phase_cfg / storage_phase_cfg
|
||||
auto cell = config_->get_config_param(is_masterchain() ? 20 : 21);
|
||||
auto cell = config->get_config_param(wc == ton::masterchainId ? 20 : 21);
|
||||
if (cell.is_null()) {
|
||||
return fatal_error("cannot fetch current gas prices and limits from masterchain configuration");
|
||||
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 fatal_error("cannot unpack 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_.global_config = config_->get_root_cell();
|
||||
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->global_config = config->get_root_cell();
|
||||
}
|
||||
{
|
||||
// compute action_phase_cfg
|
||||
block::gen::MsgForwardPrices::Record rec;
|
||||
auto cell = config_->get_config_param(24);
|
||||
auto cell = config->get_config_param(24);
|
||||
if (cell.is_null() || !tlb::unpack_cell(std::move(cell), rec)) {
|
||||
return fatal_error("cannot fetch masterchain message transfer prices from masterchain configuration");
|
||||
return td::Status::Error(-668, "cannot fetch masterchain message transfer prices from masterchain configuration");
|
||||
}
|
||||
action_phase_cfg_.fwd_mc =
|
||||
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);
|
||||
cell = config->get_config_param(25);
|
||||
if (cell.is_null() || !tlb::unpack_cell(std::move(cell), rec)) {
|
||||
return fatal_error("cannot fetch standard message transfer prices from masterchain configuration");
|
||||
return td::Status::Error(-668, "cannot fetch standard message transfer prices from masterchain configuration");
|
||||
}
|
||||
action_phase_cfg_.fwd_std =
|
||||
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->workchains = &config->get_workchain_list();
|
||||
action_phase_cfg->bounce_msg_body = (config->has_capability(ton::capBounceMsgBody) ? 256 : 0);
|
||||
}
|
||||
{
|
||||
// fetch block_grams_created
|
||||
auto cell = config_->get_config_param(14);
|
||||
auto cell = config->get_config_param(14);
|
||||
if (cell.is_null()) {
|
||||
basechain_create_fee_ = masterchain_create_fee_ = td::zero_refint();
|
||||
*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 fatal_error("cannot unpack BlockCreateFees from configuration parameter #14");
|
||||
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 true;
|
||||
return std::move(config);
|
||||
}
|
||||
|
||||
bool Collator::compute_minted_amount(block::CurrencyCollection& to_mint) {
|
||||
|
@ -2218,75 +2242,25 @@ Ref<vm::Cell> Collator::create_ordinary_transaction(Ref<vm::Cell> msg_root) {
|
|||
}
|
||||
block::Account* acc = acc_res.move_as_ok();
|
||||
assert(acc);
|
||||
if (acc->last_trans_end_lt_ >= start_lt && acc->transactions.empty()) {
|
||||
fatal_error(PSTRING() << "last transaction time in the state of account " << workchain() << ":" << addr.to_hex()
|
||||
<< " is too large");
|
||||
return {};
|
||||
}
|
||||
auto trans_min_lt = start_lt;
|
||||
if (external) {
|
||||
// transactions processing external messages must have lt larger than all processed internal messages
|
||||
trans_min_lt = std::max(trans_min_lt, last_proc_int_msg_.first);
|
||||
}
|
||||
std::unique_ptr<block::Transaction> trans =
|
||||
std::make_unique<block::Transaction>(*acc, block::Transaction::tr_ord, trans_min_lt + 1, now_, msg_root);
|
||||
bool ihr_delivered = false; // FIXME
|
||||
if (!trans->unpack_input_msg(ihr_delivered, &action_phase_cfg_)) {
|
||||
if (external) {
|
||||
// inbound external message was not accepted
|
||||
LOG(DEBUG) << "inbound external message rejected by account " << addr.to_hex()
|
||||
<< " before smart-contract execution";
|
||||
|
||||
|
||||
auto res = impl_create_ordinary_transaction(msg_root, acc, now_, start_lt,
|
||||
&storage_phase_cfg_, &compute_phase_cfg_,
|
||||
&action_phase_cfg_,
|
||||
external, last_proc_int_msg_.first
|
||||
);
|
||||
if(res.is_error()) {
|
||||
auto error = res.move_as_error();
|
||||
if(error.code() == -701) {
|
||||
// ignorable errors
|
||||
LOG(DEBUG) << error.message();
|
||||
return {};
|
||||
}
|
||||
fatal_error("cannot unpack input message for a new transaction");
|
||||
return {};
|
||||
}
|
||||
if (trans->bounce_enabled) {
|
||||
if (!trans->prepare_storage_phase(storage_phase_cfg_, true)) {
|
||||
fatal_error("cannot create storage phase of a new transaction for smart contract "s + addr.to_hex());
|
||||
return {};
|
||||
}
|
||||
if (!external && !trans->prepare_credit_phase()) {
|
||||
fatal_error("cannot create credit phase of a new transaction for smart contract "s + addr.to_hex());
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
if (!external && !trans->prepare_credit_phase()) {
|
||||
fatal_error("cannot create credit phase of a new transaction for smart contract "s + addr.to_hex());
|
||||
return {};
|
||||
}
|
||||
if (!trans->prepare_storage_phase(storage_phase_cfg_, true, true)) {
|
||||
fatal_error("cannot create storage phase of a new transaction for smart contract "s + addr.to_hex());
|
||||
return {};
|
||||
}
|
||||
}
|
||||
if (!trans->prepare_compute_phase(compute_phase_cfg_)) {
|
||||
fatal_error("cannot create compute phase of a new transaction for smart contract "s + addr.to_hex());
|
||||
return {};
|
||||
}
|
||||
if (!trans->compute_phase->accepted) {
|
||||
if (external) {
|
||||
// inbound external message was not accepted
|
||||
LOG(DEBUG) << "inbound external message rejected by transaction " << addr.to_hex();
|
||||
return {};
|
||||
} else if (trans->compute_phase->skip_reason == block::ComputePhase::sk_none) {
|
||||
fatal_error("new ordinary transaction for smart contract "s + addr.to_hex() +
|
||||
" has not been accepted by the smart contract (?)");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
if (trans->compute_phase->success && !trans->prepare_action_phase(action_phase_cfg_)) {
|
||||
fatal_error("cannot create action phase of a new transaction for smart contract "s + addr.to_hex());
|
||||
return {};
|
||||
}
|
||||
if (trans->bounce_enabled && !trans->compute_phase->success && !trans->prepare_bounce_phase(action_phase_cfg_)) {
|
||||
fatal_error("cannot create bounce phase of a new transaction for smart contract "s + addr.to_hex());
|
||||
return {};
|
||||
}
|
||||
if (!trans->serialize()) {
|
||||
fatal_error("cannot serialize new transaction for smart contract "s + addr.to_hex());
|
||||
fatal_error(std::move(error));
|
||||
return {};
|
||||
}
|
||||
std::unique_ptr<block::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");
|
||||
return {};
|
||||
|
@ -2296,6 +2270,7 @@ Ref<vm::Cell> Collator::create_ordinary_transaction(Ref<vm::Cell> msg_root) {
|
|||
fatal_error("cannot commit new transaction for smart contract "s + addr.to_hex());
|
||||
return {};
|
||||
}
|
||||
|
||||
register_new_msgs(*trans);
|
||||
update_max_lt(acc->last_trans_end_lt_);
|
||||
// temporary patch to stop producing dangerous block
|
||||
|
@ -2305,6 +2280,75 @@ Ref<vm::Cell> Collator::create_ordinary_transaction(Ref<vm::Cell> msg_root) {
|
|||
return trans_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) {
|
||||
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");
|
||||
}
|
||||
auto trans_min_lt = lt;
|
||||
if (external) {
|
||||
// transactions processing external messages must have lt larger than all processed internal messages
|
||||
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);
|
||||
bool ihr_delivered = false; // FIXME
|
||||
if (!trans->unpack_input_msg(ihr_delivered, action_phase_cfg)) {
|
||||
if (external) {
|
||||
// inbound external message was not accepted
|
||||
return td::Status::Error(-701,"inbound external message rejected by account "s + acc->addr.to_hex() +
|
||||
" before smart-contract execution");
|
||||
}
|
||||
return td::Status::Error(-669,"cannot unpack input message for a new transaction");
|
||||
}
|
||||
if (trans->bounce_enabled) {
|
||||
if (!trans->prepare_storage_phase(*storage_phase_cfg, true)) {
|
||||
return td::Status::Error(-669,"cannot create storage phase of a new transaction for smart contract "s + acc->addr.to_hex());
|
||||
}
|
||||
if (!external && !trans->prepare_credit_phase()) {
|
||||
return td::Status::Error(-669,"cannot create credit phase of a new transaction for smart contract "s + acc->addr.to_hex());
|
||||
}
|
||||
} else {
|
||||
if (!external && !trans->prepare_credit_phase()) {
|
||||
return td::Status::Error(-669,"cannot create credit phase of a new transaction for smart contract "s + acc->addr.to_hex());
|
||||
}
|
||||
if (!trans->prepare_storage_phase(*storage_phase_cfg, true, true)) {
|
||||
return td::Status::Error(-669,"cannot create storage phase of a new transaction for smart contract "s + acc->addr.to_hex());
|
||||
}
|
||||
}
|
||||
if (!trans->prepare_compute_phase(*compute_phase_cfg)) {
|
||||
return td::Status::Error(-669,"cannot create compute phase of a new transaction for smart contract "s + acc->addr.to_hex());
|
||||
}
|
||||
if (!trans->compute_phase->accepted) {
|
||||
if (external) {
|
||||
// inbound external message was not accepted
|
||||
return td::Status::Error(-701,"inbound external message rejected by transaction "s + acc->addr.to_hex());
|
||||
} else if (trans->compute_phase->skip_reason == block::ComputePhase::sk_none) {
|
||||
return td::Status::Error(-669,"new ordinary transaction for smart contract "s + acc->addr.to_hex() +
|
||||
" has not been accepted by the smart contract (?)");
|
||||
}
|
||||
}
|
||||
if (trans->compute_phase->success && !trans->prepare_action_phase(*action_phase_cfg)) {
|
||||
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->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());
|
||||
}
|
||||
if (!trans->serialize()) {
|
||||
return td::Status::Error(-669,"cannot serialize new transaction for smart contract "s + acc->addr.to_hex());
|
||||
}
|
||||
return std::move(trans);
|
||||
}
|
||||
|
||||
void Collator::update_max_lt(ton::LogicalTime lt) {
|
||||
CHECK(lt >= start_lt);
|
||||
if (lt > max_lt) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue