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

Merge branch 'testnet' into block-generation

# Conflicts:
#	adnl/adnl-query.cpp
#	crypto/block/block.tlb
#	crypto/block/mc-config.h
#	lite-client/lite-client.cpp
#	overlay/overlay-manager.h
#	overlay/overlay-peers.cpp
#	overlay/overlay.cpp
#	overlay/overlay.h
#	overlay/overlay.hpp
#	overlay/overlays.h
#	rldp-http-proxy/DNSResolver.cpp
#	rldp-http-proxy/rldp-http-proxy.cpp
#	tl/generate/scheme/ton_api.tl
#	tl/generate/scheme/ton_api.tlo
#	tl/generate/scheme/tonlib_api.tlo
#	ton/ton-types.h
#	tonlib/tonlib/ExtClient.cpp
#	tonlib/tonlib/ExtClient.h
#	tonlib/tonlib/ExtClientLazy.cpp
#	tonlib/tonlib/ExtClientOutbound.h
#	tonlib/tonlib/ExtClientRaw.h
#	tonlib/tonlib/TonlibClient.cpp
#	tonlib/tonlib/TonlibClient.h
#	tonlib/tonlib/tonlib-cli.cpp
#	validator/impl/collator.cpp
#	validator/impl/validate-query.cpp
#	validator/impl/validate-query.hpp
#	validator/manager.cpp
#	validator/state-serializer.cpp
#	validator/state-serializer.hpp
#	validator/validator-group.cpp
#	validator/validator-group.hpp
#	validator/validator.h
This commit is contained in:
SpyCheese 2022-12-22 23:37:35 +03:00
commit d652f7d706
200 changed files with 13492 additions and 2997 deletions

View file

@ -72,6 +72,7 @@ class Collator final : public td::actor::Actor {
Ref<ValidatorSet> validator_set_;
td::actor::ActorId<ValidatorManager> manager;
td::Timestamp timeout;
td::Timestamp soft_timeout_, medium_timeout_;
td::Promise<BlockCandidate> main_promise;
ton::BlockSeqno last_block_seqno{0};
ton::BlockSeqno prev_mc_block_seqno{0};

View file

@ -66,10 +66,12 @@ Collator::Collator(ShardIdFull shard, bool is_hardfork, BlockIdExt min_mastercha
, validator_set_(std::move(validator_set))
, manager(manager)
, timeout(timeout)
, soft_timeout_(td::Timestamp::at(timeout.at() - 3.0))
, medium_timeout_(td::Timestamp::at(timeout.at() - 1.5))
, main_promise(std::move(promise))
, perf_timer_("collate", 0.1, [manager](double duration) {
send_closure(manager, &ValidatorManager::add_perf_timer_stat, "collate", duration);
}) {
send_closure(manager, &ValidatorManager::add_perf_timer_stat, "collate", duration);
}) {
}
void Collator::start_up() {
@ -1592,30 +1594,22 @@ 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()
);
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());
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) {
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();
@ -1629,6 +1623,7 @@ td::Result<std::unique_ptr<block::ConfigInfo>>
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);
@ -1641,6 +1636,7 @@ td::Result<std::unique_ptr<block::ConfigInfo>>
}
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();
}
{
@ -1662,6 +1658,7 @@ td::Result<std::unique_ptr<block::ConfigInfo>>
(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
@ -1761,6 +1758,9 @@ bool Collator::init_value_create() {
}
bool Collator::do_collate() {
// After do_collate started it will not be interrupted by timeout
alarm_timestamp() = td::Timestamp::never();
LOG(DEBUG) << "do_collate() : start";
if (!fetch_config_params()) {
return fatal_error("cannot fetch required configuration parameters from masterchain state");
@ -2278,15 +2278,11 @@ Ref<vm::Cell> Collator::create_ordinary_transaction(Ref<vm::Cell> msg_root) {
block::Account* acc = acc_res.move_as_ok();
assert(acc);
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 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) {
if (error.code() == -701) {
// ignorable errors
LOG(DEBUG) << error.message();
return {};
@ -2313,16 +2309,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>> 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");
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) {
@ -2336,51 +2329,58 @@ td::Result<std::unique_ptr<block::Transaction>> Collator::impl_create_ordinary_t
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");
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());
}
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());
}
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());
}
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());
}
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());
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
auto const& cp = *trans->compute_phase;
return td::Status::Error(
-701,
PSLICE() << "inbound external message rejected by transaction " << acc->addr.to_hex() << ":\n" <<
"exitcode=" << cp.exit_code << ", steps=" << cp.vm_steps << ", gas_used=" << cp.gas_used <<
(cp.vm_log.empty() ? "" : "\nVM Log (truncated):\n..." + cp.vm_log));
} 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 (?)");
}
-701, PSLICE() << "inbound external message rejected by transaction " << acc->addr.to_hex() << ":\n"
<< "exitcode=" << cp.exit_code << ", steps=" << cp.vm_steps << ", gas_used=" << cp.gas_used
<< (cp.vm_log.empty() ? "" : "\nVM Log (truncated):\n..." + cp.vm_log));
} 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());
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->bounce_enabled && (!trans->compute_phase->success || trans->action_phase->state_size_too_big) &&
!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 td::Status::Error(-669, "cannot serialize new transaction for smart contract "s + acc->addr.to_hex());
}
return std::move(trans);
}
@ -2536,6 +2536,11 @@ int Collator::process_one_new_message(block::NewOutMsg msg, bool enqueue_only, R
block_full_ = true;
return 3;
}
if (soft_timeout_.is_in_past(td::Timestamp::now())) {
LOG(WARNING) << "soft timeout reached, stop processing new messages";
block_full_ = true;
return 3;
}
return 1;
}
@ -2816,6 +2821,11 @@ bool Collator::process_inbound_internal_messages() {
LOG(INFO) << "BLOCK FULL, stop processing inbound internal messages";
break;
}
if (soft_timeout_.is_in_past(td::Timestamp::now())) {
block_full_ = true;
LOG(WARNING) << "soft timeout reached, stop processing inbound internal messages";
break;
}
LOG(DEBUG) << "processing inbound message with (lt,hash)=(" << kv->lt << "," << kv->key.to_hex()
<< ") from neighbor #" << kv->source;
if (verbosity > 2) {
@ -2847,6 +2857,10 @@ bool Collator::process_inbound_external_messages() {
LOG(INFO) << "BLOCK FULL, stop processing external messages";
break;
}
if (medium_timeout_.is_in_past(td::Timestamp::now())) {
LOG(WARNING) << "medium timeout reached, stop processing inbound external messages";
break;
}
auto ext_msg = ext_msg_pair.first;
ton::Bits256 hash{ext_msg->get_hash().bits()};
int r = process_external_message(std::move(ext_msg));
@ -3126,7 +3140,7 @@ static int update_one_shard(block::McShardHash& info, const block::McShardHash*
if (info.is_fsm_none() && (info.want_split_ || depth < wc_info->min_split) && depth < wc_info->max_split &&
depth < 60) {
// prepare split
info.set_fsm_split(now + ton::split_merge_delay, ton::split_merge_interval);
info.set_fsm_split(now + wc_info->split_merge_delay, wc_info->split_merge_interval);
changed = true;
LOG(INFO) << "preparing to split shard " << info.shard().to_str() << " during " << info.fsm_utime() << " .. "
<< info.fsm_utime_end();
@ -3134,7 +3148,7 @@ static int update_one_shard(block::McShardHash& info, const block::McShardHash*
sibling && !sibling->before_split_ && sibling->is_fsm_none() &&
(sibling->want_merge_ || depth > wc_info->max_split)) {
// prepare merge
info.set_fsm_merge(now + ton::split_merge_delay, ton::split_merge_interval);
info.set_fsm_merge(now + wc_info->split_merge_delay, wc_info->split_merge_interval);
changed = true;
LOG(INFO) << "preparing to merge shard " << info.shard().to_str() << " with " << sibling->shard().to_str()
<< " during " << info.fsm_utime() << " .. " << info.fsm_utime_end();
@ -3216,7 +3230,7 @@ bool Collator::create_mc_state_extra() {
" contains an invalid configuration in its data, IGNORING CHANGES";
ignore_cfg_changes = true;
} else {
cfg0 = cfg_dict.lookup_ref(td::BitArray<32>{(long long) 0});
cfg0 = cfg_dict.lookup_ref(td::BitArray<32>{(long long)0});
}
bool changed_cfg = false;
if (cfg0.not_null()) {

View file

@ -38,8 +38,9 @@ ExtMessageQ::ExtMessageQ(td::BufferSlice data, td::Ref<vm::Cell> root, AccountId
hash_ = block::compute_file_hash(data_);
}
td::Result<Ref<ExtMessageQ>> ExtMessageQ::create_ext_message(td::BufferSlice data) {
if (data.size() > max_ext_msg_size) {
td::Result<Ref<ExtMessageQ>> ExtMessageQ::create_ext_message(td::BufferSlice data,
block::SizeLimitsConfig::ExtMsgLimits limits) {
if (data.size() > limits.max_size) {
return td::Status::Error("external message too large, rejecting");
}
vm::BagOfCells boc;
@ -54,7 +55,7 @@ td::Result<Ref<ExtMessageQ>> ExtMessageQ::create_ext_message(td::BufferSlice dat
if (ext_msg->get_level() != 0) {
return td::Status::Error("external message must have zero level");
}
if (ext_msg->get_depth() >= max_ext_msg_depth) {
if (ext_msg->get_depth() >= limits.max_depth) {
return td::Status::Error("external message is too deep");
}
vm::CellSlice cs{vm::NoVmOrd{}, ext_msg};
@ -85,21 +86,25 @@ td::Result<Ref<ExtMessageQ>> ExtMessageQ::create_ext_message(td::BufferSlice dat
return Ref<ExtMessageQ>{true, std::move(data), std::move(ext_msg), dest_prefix, wc, addr};
}
void ExtMessageQ::run_message(td::BufferSlice data, td::actor::ActorId<ton::validator::ValidatorManager> manager,
td::Promise<td::Unit> promise) {
auto R = create_ext_message(std::move(data));
void ExtMessageQ::run_message(td::BufferSlice data, block::SizeLimitsConfig::ExtMsgLimits limits,
td::actor::ActorId<ton::validator::ValidatorManager> manager,
td::Promise<td::Ref<ExtMessage>> promise) {
auto R = create_ext_message(std::move(data), limits);
if (R.is_error()) {
return promise.set_error(R.move_as_error_prefix("failed to parse external message "));
}
auto M = R.move_as_ok();
auto root = M->root_cell();
block::gen::CommonMsgInfo::Record_ext_in_msg_info info;
tlb::unpack_cell_inexact(root, info); // checked in create message
tlb::unpack_cell_inexact(root, info); // checked in create message
ton::StdSmcAddress addr = M->addr();
ton::WorkchainId wc = M->wc();
run_fetch_account_state(wc, addr, manager,
[promise = std::move(promise), msg_root = root, wc = wc](td::Result<std::tuple<td::Ref<vm::CellSlice>,UnixTime,LogicalTime,std::unique_ptr<block::ConfigInfo>>> res) mutable {
run_fetch_account_state(
wc, addr, manager,
[promise = std::move(promise), msg_root = root, wc,
M](td::Result<std::tuple<td::Ref<vm::CellSlice>, UnixTime, LogicalTime, std::unique_ptr<block::ConfigInfo>>>
res) mutable {
if (res.is_error()) {
promise.set_error(td::Status::Error(PSLICE() << "Failed to get account state"));
} else {
@ -109,20 +114,19 @@ void ExtMessageQ::run_message(td::BufferSlice data, td::actor::ActorId<ton::vali
auto utime = std::get<1>(tuple);
auto lt = std::get<2>(tuple);
auto config = std::move(std::get<3>(tuple));
if(!acc.unpack(shard_acc, {}, utime, false)) {
if (!acc.unpack(shard_acc, {}, utime, false)) {
promise.set_error(td::Status::Error(PSLICE() << "Failed to unpack account state"));
} else {
auto status = run_message_on_account(wc, &acc, utime, lt + 1, msg_root, std::move(config));
if (status.is_ok()) {
promise.set_value(td::Unit());
promise.set_value(std::move(M));
} else {
promise.set_error(td::Status::Error(
PSLICE() << "External message was not accepted\n" << status.message()));
promise.set_error(td::Status::Error(PSLICE() << "External message was not accepted\n"
<< status.message()));
}
}
}
}
);
});
}
td::Status ExtMessageQ::run_message_on_account(ton::WorkchainId wc,

View file

@ -37,8 +37,6 @@ class ExtMessageQ : public ExtMessage {
ton::StdSmcAddress addr_;
public:
static constexpr unsigned max_ext_msg_size = 65535;
static constexpr unsigned max_ext_msg_depth = 512;
AccountIdPrefixFull shard() const override {
return addr_prefix_;
}
@ -59,10 +57,13 @@ class ExtMessageQ : public ExtMessage {
return addr_;
}
ExtMessageQ(td::BufferSlice data, td::Ref<vm::Cell> root, AccountIdPrefixFull shard, ton::WorkchainId wc, ton::StdSmcAddress addr);
static td::Result<td::Ref<ExtMessageQ>> create_ext_message(td::BufferSlice data);
static void run_message(td::BufferSlice data, td::actor::ActorId<ton::validator::ValidatorManager> manager,
td::Promise<td::Unit> promise);
ExtMessageQ(td::BufferSlice data, td::Ref<vm::Cell> root, AccountIdPrefixFull shard, ton::WorkchainId wc,
ton::StdSmcAddress addr);
static td::Result<td::Ref<ExtMessageQ>> create_ext_message(td::BufferSlice data,
block::SizeLimitsConfig::ExtMsgLimits limits);
static void run_message(td::BufferSlice data, block::SizeLimitsConfig::ExtMsgLimits limits,
td::actor::ActorId<ton::validator::ValidatorManager> manager,
td::Promise<td::Ref<ExtMessage>> promise);
static td::Status run_message_on_account(ton::WorkchainId wc,
block::Account* acc,
UnixTime utime, LogicalTime lt,

View file

@ -111,13 +111,16 @@ td::Ref<BlockSignatureSet> create_signature_set(std::vector<BlockSignature> sig_
return td::Ref<BlockSignatureSetQ>{true, std::move(sig_set)};
}
td::Result<td::Ref<ExtMessage>> create_ext_message(td::BufferSlice data) {
TRY_RESULT(res, ExtMessageQ::create_ext_message(std::move(data)));
td::Result<td::Ref<ExtMessage>> create_ext_message(td::BufferSlice data,
block::SizeLimitsConfig::ExtMsgLimits limits) {
TRY_RESULT(res, ExtMessageQ::create_ext_message(std::move(data), limits));
return std::move(res);
}
void run_check_external_message(td::BufferSlice data, td::actor::ActorId<ValidatorManager> manager, td::Promise<td::Unit> promise) {
ExtMessageQ::run_message(std::move(data), std::move(manager), std::move(promise));
void run_check_external_message(td::BufferSlice data, block::SizeLimitsConfig::ExtMsgLimits limits,
td::actor::ActorId<ValidatorManager> manager,
td::Promise<td::Ref<ExtMessage>> promise) {
ExtMessageQ::run_message(std::move(data), limits, std::move(manager), std::move(promise));
}
td::Result<td::Ref<IhrMessage>> create_ihr_message(td::BufferSlice data) {

View file

@ -153,6 +153,10 @@ void LiteQuery::start_up() {
this->perform_getAccountState(ton::create_block_id(q.id_), static_cast<WorkchainId>(q.account_->workchain_),
q.account_->id_, 0);
},
[&](lite_api::liteServer_getAccountStatePrunned& q) {
this->perform_getAccountState(ton::create_block_id(q.id_), static_cast<WorkchainId>(q.account_->workchain_),
q.account_->id_, 0x40000000);
},
[&](lite_api::liteServer_getOneTransaction& q) {
this->perform_getOneTransaction(ton::create_block_id(q.id_),
static_cast<WorkchainId>(q.account_->workchain_), q.account_->id_,
@ -228,7 +232,7 @@ void LiteQuery::perform_getMasterchainInfo(int mode) {
return;
}
td::actor::send_closure_later(
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
manager_, &ton::validator::ValidatorManager::get_last_liteserver_state_block,
[Self = actor_id(this), return_state = bool(acc_state_promise_), mode](td::Result<std::pair<Ref<ton::validator::MasterchainState>, BlockIdExt>> res) {
if (res.is_error()) {
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
@ -482,20 +486,13 @@ void LiteQuery::perform_sendMessage(td::BufferSlice data) {
auto copy = data.clone();
td::actor::send_closure_later(
manager_, &ValidatorManager::check_external_message, std::move(copy),
[Self = actor_id(this), data = std::move(data), manager = manager_](td::Result<td::Unit> res) mutable {
[Self = actor_id(this), data = std::move(data), manager = manager_](td::Result<td::Ref<ExtMessage>> res) mutable {
if(res.is_error()) {
td::actor::send_closure(Self, &LiteQuery::abort_query,
res.move_as_error_prefix("cannot apply external message to current state : "s));
} else {
auto crm = ton::validator::create_ext_message(std::move(data));
if (crm.is_error()) {
//UNREACHABLE, checks in check_external_message,
td::actor::send_closure(Self, &LiteQuery::abort_query,
crm.move_as_error());
return;
}
LOG(INFO) << "sending an external message to validator manager";
td::actor::send_closure_later(manager, &ValidatorManager::send_external_message, crm.move_as_ok());
td::actor::send_closure_later(manager, &ValidatorManager::send_external_message, res.move_as_ok());
auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_sendMsgStatus>(1);
td::actor::send_closure(Self, &LiteQuery::finish_query, std::move(b));
}
@ -779,9 +776,9 @@ void LiteQuery::perform_getAccountState(BlockIdExt blkid, WorkchainId workchain,
set_continuation([&]() -> void { continue_getAccountState(); });
request_mc_block_data_state(blkid);
} else {
LOG(INFO) << "sending a get_top_masterchain_state_block query to manager";
LOG(INFO) << "sending a get_last_liteserver_state_block query to manager";
td::actor::send_closure_later(
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
manager_, &ton::validator::ValidatorManager::get_last_liteserver_state_block,
[Self = actor_id(this)](td::Result<std::pair<Ref<ton::validator::MasterchainState>, BlockIdExt>> res) -> void {
if (res.is_error()) {
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
@ -858,7 +855,7 @@ void LiteQuery::perform_getLibraries(std::vector<td::Bits256> library_list) {
sort( library_list.begin(), library_list.end() );
library_list.erase( unique( library_list.begin(), library_list.end() ), library_list.end() );
td::actor::send_closure_later(
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
manager_, &ton::validator::ValidatorManager::get_last_liteserver_state_block,
[Self = actor_id(this), library_list](td::Result<std::pair<Ref<ton::validator::MasterchainState>, BlockIdExt>> res) -> void {
if (res.is_error()) {
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
@ -1213,6 +1210,19 @@ void LiteQuery::finish_getAccountState(td::BufferSlice shard_proof) {
}
td::BufferSlice data;
if (acc_root.not_null()) {
if (mode_ & 0x40000000) {
vm::MerkleProofBuilder mpb{acc_root};
// account_none$0 = Account;
// account$1 addr:MsgAddressInt storage_stat:StorageInfo storage:AccountStorage = Account;
// account_storage$_ last_trans_lt:uint64 balance:CurrencyCollection state:AccountState = AccountStorage;
// account_active$1 _:StateInit = AccountState;
auto S = mpb.root()->load_cell();
if (S.is_error()) {
fatal_error(S.move_as_error_prefix("Failed to load account: "));
return;
}
acc_root = mpb.extract_proof();
}
auto res = vm::std_boc_serialize(std::move(acc_root));
if (res.is_error()) {
fatal_error(res.move_as_error());
@ -1532,7 +1542,7 @@ void LiteQuery::perform_getShardInfo(BlockIdExt blkid, ShardIdFull shard, bool e
}
void LiteQuery::load_prevKeyBlock(ton::BlockIdExt blkid, td::Promise<std::pair<BlockIdExt, Ref<BlockQ>>> promise) {
td::actor::send_closure_later(manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
td::actor::send_closure_later(manager_, &ton::validator::ValidatorManager::get_last_liteserver_state_block,
[Self = actor_id(this), blkid, promise = std::move(promise)](
td::Result<std::pair<Ref<MasterchainState>, BlockIdExt>> res) mutable {
td::actor::send_closure_later(Self, &LiteQuery::continue_loadPrevKeyBlock, blkid,
@ -1955,7 +1965,7 @@ void LiteQuery::perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to,
});
} else {
td::actor::send_closure_later(
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
manager_, &ton::validator::ValidatorManager::get_last_liteserver_state_block,
[Self = actor_id(this), from, to, mode](td::Result<std::pair<Ref<MasterchainState>, BlockIdExt>> res) {
if (res.is_error()) {
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
@ -1968,7 +1978,7 @@ void LiteQuery::perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to,
}
} else if (mode & 2) {
td::actor::send_closure_later(
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
manager_, &ton::validator::ValidatorManager::get_last_liteserver_state_block,
[Self = actor_id(this), from, mode](td::Result<std::pair<Ref<MasterchainState>, BlockIdExt>> res) {
if (res.is_error()) {
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());

View file

@ -126,6 +126,10 @@ class MasterchainStateQ : public MasterchainState, public ShardStateQ {
ValidatorSessionConfig get_consensus_config() const override {
return config_->get_consensus_config();
}
block::SizeLimitsConfig::ExtMsgLimits get_ext_msg_limits() const override {
auto R = config_->get_size_limits_config();
return R.is_error() ? block::SizeLimitsConfig::ExtMsgLimits() : R.ok_ref().ext_msg_limits;
}
BlockIdExt last_key_block_id() const override;
BlockIdExt next_key_block_id(BlockSeqno seqno) const override;
BlockIdExt prev_key_block_id(BlockSeqno seqno) const override;

View file

@ -67,8 +67,8 @@ ValidateQuery::ValidateQuery(ShardIdFull shard, BlockIdExt min_masterchain_block
, shard_pfx_(shard_.shard)
, shard_pfx_len_(ton::shard_prefix_length(shard_))
, perf_timer_("validateblock", 0.1, [manager](double duration) {
send_closure(manager, &ValidatorManager::add_perf_timer_stat, "validateblock", duration);
}) {
send_closure(manager, &ValidatorManager::add_perf_timer_stat, "validateblock", duration);
}) {
}
void ValidateQuery::alarm() {
@ -737,6 +737,8 @@ bool ValidateQuery::try_unpack_mc_state() {
return fatal_error(limits.move_as_error());
}
block_limits_ = limits.move_as_ok();
block_limits_->start_lt = start_lt_;
block_limit_status_ = std::make_unique<block::BlockLimitStatus>(*block_limits_);
if (!fetch_config_params()) {
return false;
}
@ -765,6 +767,14 @@ bool ValidateQuery::fetch_config_params() {
// recover (not generate) rand seed from block header
CHECK(!rand_seed_.is_zero());
}
block::SizeLimitsConfig size_limits;
{
auto res = config_->get_size_limits_config();
if (res.is_error()) {
return fatal_error(res.move_as_error());
}
size_limits = res.move_as_ok();
}
{
// compute compute_phase_cfg / storage_phase_cfg
auto cell = config_->get_config_param(is_masterchain() ? 20 : 21);
@ -777,6 +787,7 @@ bool ValidateQuery::fetch_config_params() {
}
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();
}
{
@ -798,6 +809,7 @@ bool ValidateQuery::fetch_config_params() {
(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
@ -998,6 +1010,16 @@ bool ValidateQuery::compute_prev_state() {
return compute_prev_state_from_collated_data();
}
CHECK(prev_states.size() == 1u + after_merge_);
// Extend validator timeout if previous block is too old
UnixTime prev_ts = prev_states[0]->get_unix_time();
if (after_merge_) {
prev_ts = std::max(prev_ts, prev_states[1]->get_unix_time());
}
td::Timestamp new_timeout = td::Timestamp::in(std::min(60.0, (td::Clocks::system() - (double)prev_ts) / 2));
if (timeout < new_timeout) {
alarm_timestamp() = timeout = new_timeout;
}
prev_state_root_ = prev_states[0]->root_cell();
CHECK(prev_state_root_.not_null());
if (after_merge_) {
@ -1690,8 +1712,8 @@ bool ValidateQuery::check_one_shard(const block::McShardHash& info, const block:
(sibling->want_merge_ || depth > wc_info->max_split);
if (!fsm_inherited && !info.is_fsm_none()) {
if (info.fsm_utime() < now_ || info.fsm_utime_end() <= info.fsm_utime() ||
info.fsm_utime_end() < info.fsm_utime() + ton::min_split_merge_interval ||
info.fsm_utime_end() > now_ + ton::max_split_merge_delay) {
info.fsm_utime_end() < info.fsm_utime() + wc_info->min_split_merge_interval ||
info.fsm_utime_end() > now_ + wc_info->max_split_merge_delay) {
return reject_query(PSTRING() << "incorrect future split/merge interval " << info.fsm_utime() << " .. "
<< info.fsm_utime_end() << " set for shard " << shard.to_str()
<< " in new shard configuration (it is " << now_ << " now)");
@ -4183,6 +4205,9 @@ std::unique_ptr<block::Account> ValidateQuery::unpack_account(td::ConstBitPtr ad
bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalTime lt, Ref<vm::Cell> trans_root,
bool is_first, bool is_last) {
if (!check_timeout()) {
return false;
}
LOG(DEBUG) << "checking transaction " << lt << " of account " << account.addr.to_hex();
const StdSmcAddress& addr = account.addr;
block::gen::Transaction::Record trans;
@ -4388,7 +4413,8 @@ 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.orig_status == block::Account::acc_active) {
(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");
@ -4417,6 +4443,13 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT
int trans_type = block::Transaction::tr_none;
switch (tag) {
case block::gen::TransactionDescr::trans_ord: {
if (!block_limit_status_->fits(block::ParamLimits::cl_medium)) {
return reject_query(PSTRING() << "cannod add ordinary transaction because hard block limits are exceeded: "
<< "gas_used=" << block_limit_status_->gas_used
<< "(limit=" << block_limits_->gas.hard() << "), "
<< "lt_delta=" << block_limit_status_->cur_lt - block_limits_->start_lt
<< "(limit=" << block_limits_->lt_delta.hard() << ")");
}
trans_type = block::Transaction::tr_ord;
if (in_msg_root.is_null()) {
return reject_query(PSTRING() << "ordinary transaction " << lt << " of account " << addr.to_hex()
@ -4554,7 +4587,8 @@ 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->prepare_bounce_phase(action_phase_cfg_)) {
if (trs->bounce_enabled && (!trs->compute_phase->success || trs->action_phase->state_size_too_big) &&
!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());
}
@ -4562,7 +4596,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT
return reject_query(PSTRING() << "cannot re-create the serialization of transaction " << lt
<< " for smart contract " << addr.to_hex());
}
if (block_limit_status_ && !trs->update_limits(*block_limit_status_)) {
if (!trs->update_limits(*block_limit_status_, false)) {
return fatal_error(PSTRING() << "cannot update block limit status to include transaction " << lt << " of account "
<< addr.to_hex());
}
@ -5037,7 +5071,7 @@ bool ValidateQuery::check_config_update(Ref<vm::CellSlice> old_conf_params, Ref<
return reject_query("no important parameters have been changed, but the block is marked as a key block");
}
vm::Dictionary dict1{ocfg_root, 32};
auto param0 = dict1.lookup_ref(td::BitArray<32>{(long long) 0});
auto param0 = dict1.lookup_ref(td::BitArray<32>{(long long)0});
if (param0.is_null()) {
if (cfg_acc_changed) {
return reject_query("new state of old configuration smart contract "s + old_cfg_addr.to_hex() +

View file

@ -371,6 +371,14 @@ class ValidateQuery : public td::actor::Actor {
bool check_mc_block_extra();
Ref<vm::Cell> get_virt_state_root(td::Bits256 block_root_hash);
bool check_timeout() {
if (timeout && timeout.is_in_past()) {
abort_query(td::Status::Error(ErrorCode::timeout, "timeout"));
return false;
}
return true;
}
};
} // namespace validator