mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Merge branch 'testnet' into block-generation
# Conflicts: # crypto/block/mc-config.cpp # crypto/block/mc-config.h
This commit is contained in:
commit
e216651112
41 changed files with 1233 additions and 192 deletions
|
@ -136,7 +136,8 @@ void FullNodeShardImpl::check_broadcast(PublicKeyHash src, td::BufferSlice broad
|
|||
}
|
||||
|
||||
auto q = B.move_as_ok();
|
||||
if (!processed_ext_msg_broadcasts_.insert(td::sha256_bits256(q->message_->data_)).second) {
|
||||
auto hash = td::sha256_bits256(q->message_->data_);
|
||||
if (!processed_ext_msg_broadcasts_.insert(hash).second) {
|
||||
return promise.set_error(td::Status::Error("duplicate external message broadcast"));
|
||||
}
|
||||
if (config_.ext_messages_broadcast_disabled_) {
|
||||
|
@ -147,6 +148,11 @@ void FullNodeShardImpl::check_broadcast(PublicKeyHash src, td::BufferSlice broad
|
|||
}
|
||||
};
|
||||
}
|
||||
if (my_ext_msg_broadcasts_.count(hash)) {
|
||||
// Don't re-check messages that were sent by us
|
||||
promise.set_result(td::Unit());
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::check_external_message,
|
||||
std::move(q->message_->data_),
|
||||
promise.wrap([](td::Ref<ExtMessage>) { return td::Unit(); }));
|
||||
|
@ -821,9 +827,11 @@ void FullNodeShardImpl::send_external_message(td::BufferSlice data) {
|
|||
});
|
||||
return;
|
||||
}
|
||||
if (!processed_ext_msg_broadcasts_.insert(td::sha256_bits256(data)).second) {
|
||||
td::Bits256 hash = td::sha256_bits256(data);
|
||||
if (processed_ext_msg_broadcasts_.count(hash)) {
|
||||
return;
|
||||
}
|
||||
my_ext_msg_broadcasts_.insert(hash);
|
||||
auto B = create_serialize_tl_object<ton_api::tonNode_externalMessageBroadcast>(
|
||||
create_tl_object<ton_api::tonNode_externalMessage>(std::move(data)));
|
||||
if (B.size() <= overlay::Overlays::max_simple_broadcast_size()) {
|
||||
|
@ -1016,6 +1024,7 @@ void FullNodeShardImpl::alarm() {
|
|||
}
|
||||
if (cleanup_processed_ext_msg_at_ && cleanup_processed_ext_msg_at_.is_in_past()) {
|
||||
processed_ext_msg_broadcasts_.clear();
|
||||
my_ext_msg_broadcasts_.clear();
|
||||
cleanup_processed_ext_msg_at_ = td::Timestamp::in(60.0);
|
||||
}
|
||||
alarm_timestamp().relax(sync_completed_at_);
|
||||
|
|
|
@ -280,6 +280,7 @@ class FullNodeShardImpl : public FullNodeShard {
|
|||
|
||||
FullNodeConfig config_;
|
||||
|
||||
std::set<td::Bits256> my_ext_msg_broadcasts_;
|
||||
std::set<td::Bits256> processed_ext_msg_broadcasts_;
|
||||
td::Timestamp cleanup_processed_ext_msg_at_;
|
||||
};
|
||||
|
|
|
@ -157,7 +157,7 @@ void LiteQuery::start_up() {
|
|||
});
|
||||
return;
|
||||
}
|
||||
use_cache_ = !cache_.empty() && query_obj_->get_id() == lite_api::liteServer_runSmcMethod::ID;
|
||||
use_cache_ = use_cache();
|
||||
if (use_cache_) {
|
||||
cache_key_ = td::sha256_bits256(query_);
|
||||
td::actor::send_closure(
|
||||
|
@ -173,6 +173,22 @@ void LiteQuery::start_up() {
|
|||
}
|
||||
}
|
||||
|
||||
bool LiteQuery::use_cache() {
|
||||
if (cache_.empty()) {
|
||||
return false;
|
||||
}
|
||||
bool use = false;
|
||||
lite_api::downcast_call(
|
||||
*query_obj_,
|
||||
td::overloaded(
|
||||
[&](lite_api::liteServer_runSmcMethod& q) {
|
||||
// wc=-1, seqno=-1 means "use latest mc block"
|
||||
use = q.id_->workchain_ != masterchainId || q.id_->seqno_ != -1;
|
||||
},
|
||||
[&](auto& obj) { use = false; }));
|
||||
return use;
|
||||
}
|
||||
|
||||
void LiteQuery::perform() {
|
||||
td::actor::send_closure(manager_, &ValidatorManager::add_lite_query_stats, query_obj_->get_id());
|
||||
lite_api::downcast_call(
|
||||
|
@ -848,7 +864,7 @@ void LiteQuery::perform_runSmcMethod(BlockIdExt blkid, WorkchainId workchain, St
|
|||
fatal_error("more than 64k parameter bytes passed");
|
||||
return;
|
||||
}
|
||||
if (mode & ~0x1f) {
|
||||
if (mode & ~0x3f) {
|
||||
fatal_error("unsupported mode in runSmcMethod");
|
||||
return;
|
||||
}
|
||||
|
@ -1245,8 +1261,24 @@ void LiteQuery::finish_getAccountState(td::BufferSlice shard_proof) {
|
|||
return;
|
||||
}
|
||||
if (mode_ & 0x10000) {
|
||||
finish_runSmcMethod(std::move(shard_proof), proof.move_as_ok(), std::move(acc_root), sstate.gen_utime,
|
||||
sstate.gen_lt);
|
||||
if (!mc_state_.is_null()) {
|
||||
finish_runSmcMethod(std::move(shard_proof), proof.move_as_ok(), std::move(acc_root), sstate.gen_utime,
|
||||
sstate.gen_lt);
|
||||
return;
|
||||
}
|
||||
shard_proof_ = std::move(shard_proof);
|
||||
proof_ = proof.move_as_ok();
|
||||
set_continuation(
|
||||
[&, base_blk_id = base_blk_id_, acc_root, utime = sstate.gen_utime, lt = sstate.gen_lt]() mutable -> void {
|
||||
base_blk_id_ = base_blk_id; // It gets overridden by request_mc_block_data_state
|
||||
finish_runSmcMethod(std::move(shard_proof_), std::move(proof_), std::move(acc_root), utime, lt);
|
||||
});
|
||||
td::optional<BlockIdExt> master_ref = state_->get_master_ref();
|
||||
if (!master_ref) {
|
||||
fatal_error("masterchain ref block is not available");
|
||||
return;
|
||||
}
|
||||
request_mc_block_data_state(master_ref.value());
|
||||
return;
|
||||
}
|
||||
td::BufferSlice data;
|
||||
|
@ -1283,25 +1315,45 @@ void LiteQuery::finish_getAccountState(td::BufferSlice shard_proof) {
|
|||
|
||||
// same as in lite-client/lite-client-common.cpp
|
||||
static td::Ref<vm::Tuple> prepare_vm_c7(ton::UnixTime now, ton::LogicalTime lt, td::Ref<vm::CellSlice> my_addr,
|
||||
const block::CurrencyCollection& balance) {
|
||||
const block::CurrencyCollection& balance,
|
||||
const block::ConfigInfo* config = nullptr, td::Ref<vm::Cell> my_code = {},
|
||||
td::RefInt256 due_payment = td::zero_refint()) {
|
||||
td::BitArray<256> rand_seed;
|
||||
td::RefInt256 rand_seed_int{true};
|
||||
td::Random::secure_bytes(rand_seed.as_slice());
|
||||
if (!rand_seed_int.unique_write().import_bits(rand_seed.cbits(), 256, false)) {
|
||||
return {};
|
||||
}
|
||||
auto tuple = vm::make_tuple_ref(td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea
|
||||
td::make_refint(0), // actions:Integer
|
||||
td::make_refint(0), // msgs_sent:Integer
|
||||
td::make_refint(now), // unixtime:Integer
|
||||
td::make_refint(lt), // block_lt:Integer
|
||||
td::make_refint(lt), // trans_lt:Integer
|
||||
std::move(rand_seed_int), // rand_seed:Integer
|
||||
balance.as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)]
|
||||
my_addr, // myself:MsgAddressInt
|
||||
vm::StackEntry()); // global_config:(Maybe Cell) ] = SmartContractInfo;
|
||||
LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string();
|
||||
return vm::make_tuple_ref(std::move(tuple));
|
||||
std::vector<vm::StackEntry> tuple = {
|
||||
td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea
|
||||
td::make_refint(0), // actions:Integer
|
||||
td::make_refint(0), // msgs_sent:Integer
|
||||
td::make_refint(now), // unixtime:Integer
|
||||
td::make_refint(lt), // block_lt:Integer
|
||||
td::make_refint(lt), // trans_lt:Integer
|
||||
std::move(rand_seed_int), // rand_seed:Integer
|
||||
balance.as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)]
|
||||
my_addr, // myself:MsgAddressInt
|
||||
config ? config->get_root_cell() : vm::StackEntry() // global_config:(Maybe Cell) ] = SmartContractInfo;
|
||||
};
|
||||
if (config && config->get_global_version() >= 4) {
|
||||
tuple.push_back(my_code); // code:Cell
|
||||
tuple.push_back(block::CurrencyCollection::zero().as_vm_tuple()); // in_msg_value:[Integer (Maybe Cell)]
|
||||
tuple.push_back(td::zero_refint()); // storage_fees:Integer
|
||||
|
||||
// [ wc:Integer shard:Integer seqno:Integer root_hash:Integer file_hash:Integer] = BlockId;
|
||||
// [ last_mc_blocks:[BlockId...]
|
||||
// prev_key_block:BlockId ] : PrevBlocksInfo
|
||||
auto info = config->get_prev_blocks_info();
|
||||
tuple.push_back(info.is_ok() ? info.move_as_ok() : vm::StackEntry());
|
||||
}
|
||||
if (config && config->get_global_version() >= 6) {
|
||||
tuple.push_back(config->get_unpacked_config_tuple(now)); // unpacked_config_tuple:[...]
|
||||
tuple.push_back(due_payment); // due_payment:Integer
|
||||
}
|
||||
auto tuple_ref = td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(tuple));
|
||||
LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple_ref).to_string();
|
||||
return vm::make_tuple_ref(std::move(tuple_ref));
|
||||
}
|
||||
|
||||
void LiteQuery::finish_runSmcMethod(td::BufferSlice shard_proof, td::BufferSlice state_proof, Ref<vm::Cell> acc_root,
|
||||
|
@ -1320,12 +1372,14 @@ void LiteQuery::finish_runSmcMethod(td::BufferSlice shard_proof, td::BufferSlice
|
|||
}
|
||||
vm::MerkleProofBuilder pb{std::move(acc_root)};
|
||||
block::gen::Account::Record_account acc;
|
||||
block::gen::StorageInfo::Record storage_info;
|
||||
block::gen::AccountStorage::Record store;
|
||||
block::CurrencyCollection balance;
|
||||
block::gen::StateInit::Record state_init;
|
||||
if (!(tlb::unpack_cell(pb.root(), acc) && tlb::csr_unpack(std::move(acc.storage), store) &&
|
||||
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))) {
|
||||
store.state.write().advance(1) && tlb::csr_unpack(std::move(store.state), state_init) &&
|
||||
tlb::csr_unpack(std::move(acc.storage_stat), storage_info))) {
|
||||
LOG(INFO) << "error unpacking account state, or account is frozen or uninitialized";
|
||||
td::Result<td::BufferSlice> proof_boc;
|
||||
if (mode & 2) {
|
||||
|
@ -1346,12 +1400,35 @@ void LiteQuery::finish_runSmcMethod(td::BufferSlice shard_proof, td::BufferSlice
|
|||
}
|
||||
auto code = state_init.code->prefetch_ref();
|
||||
auto data = state_init.data->prefetch_ref();
|
||||
auto acc_libs = state_init.library->prefetch_ref();
|
||||
long long gas_limit = client_method_gas_limit;
|
||||
td::RefInt256 due_payment;
|
||||
if (storage_info.due_payment.write().fetch_long(1)) {
|
||||
due_payment = block::tlb::t_Grams.as_integer(storage_info.due_payment);
|
||||
} else {
|
||||
due_payment = td::zero_refint();
|
||||
}
|
||||
LOG(DEBUG) << "creating VM with gas limit " << gas_limit;
|
||||
// **** INIT VM ****
|
||||
auto r_config = block::ConfigInfo::extract_config(
|
||||
mc_state_->root_cell(),
|
||||
block::ConfigInfo::needLibraries | block::ConfigInfo::needCapabilities | block::ConfigInfo::needPrevBlocks);
|
||||
if (r_config.is_error()) {
|
||||
fatal_error(r_config.move_as_error());
|
||||
return;
|
||||
}
|
||||
auto config = r_config.move_as_ok();
|
||||
std::vector<td::Ref<vm::Cell>> libraries;
|
||||
if (config->get_libraries_root().not_null()) {
|
||||
libraries.push_back(config->get_libraries_root());
|
||||
}
|
||||
if (acc_libs.not_null()) {
|
||||
libraries.push_back(acc_libs);
|
||||
}
|
||||
vm::GasLimits gas{gas_limit, gas_limit};
|
||||
vm::VmState vm{std::move(code), std::move(stack_), gas, 1, std::move(data), vm::VmLog::Null()};
|
||||
auto c7 = prepare_vm_c7(gen_utime, gen_lt, td::make_ref<vm::CellSlice>(acc.addr->clone()), balance);
|
||||
vm::VmState vm{code, std::move(stack_), gas, 1, std::move(data), vm::VmLog::Null(), std::move(libraries)};
|
||||
auto c7 = prepare_vm_c7(gen_utime, gen_lt, td::make_ref<vm::CellSlice>(acc.addr->clone()), balance, config.get(),
|
||||
std::move(code), due_payment);
|
||||
vm.set_c7(c7); // tuple with SmartContractInfo
|
||||
// vm.incr_stack_trace(1); // enable stack dump after each step
|
||||
LOG(INFO) << "starting VM to run GET-method of smart contract " << acc_workchain_ << ":" << acc_addr_.to_hex();
|
||||
|
@ -1367,6 +1444,9 @@ void LiteQuery::finish_runSmcMethod(td::BufferSlice shard_proof, td::BufferSlice
|
|||
td::BufferSlice c7_info, result;
|
||||
if (mode & 8) {
|
||||
// serialize c7
|
||||
if (!(mode & 32)) {
|
||||
c7 = prepare_vm_c7(gen_utime, gen_lt, td::make_ref<vm::CellSlice>(acc.addr->clone()), balance);
|
||||
}
|
||||
vm::CellBuilder cb;
|
||||
if (!(vm::StackEntry{std::move(c7)}.serialize(cb) && cb.finalize_to(cell))) {
|
||||
fatal_error("cannot serialize c7");
|
||||
|
|
|
@ -62,7 +62,7 @@ class LiteQuery : public td::actor::Actor {
|
|||
td::BufferSlice buffer_;
|
||||
std::function<void()> continuation_;
|
||||
bool cont_set_{false};
|
||||
td::BufferSlice shard_proof_;
|
||||
td::BufferSlice shard_proof_, proof_;
|
||||
std::vector<Ref<vm::Cell>> roots_;
|
||||
std::vector<Ref<td::CntObject>> aux_objs_;
|
||||
std::vector<ton::BlockIdExt> blk_ids_;
|
||||
|
@ -98,6 +98,7 @@ class LiteQuery : public td::actor::Actor {
|
|||
bool finish_query(td::BufferSlice result, bool skip_cache_update = false);
|
||||
void alarm() override;
|
||||
void start_up() override;
|
||||
bool use_cache();
|
||||
void perform();
|
||||
void perform_getTime();
|
||||
void perform_getVersion();
|
||||
|
|
|
@ -129,6 +129,15 @@ td::Status ShardStateQ::init() {
|
|||
" contains BlockId " + hdr_id.to_str() +
|
||||
" different from the one originally required");
|
||||
}
|
||||
if (info.r1.master_ref.write().fetch_long(1)) {
|
||||
BlockIdExt mc_id;
|
||||
if (!block::tlb::t_ExtBlkRef.unpack(info.r1.master_ref, mc_id, nullptr)) {
|
||||
return td::Status::Error(-668, "cannot unpack master_ref in shardchain state of "s + blkid.to_str());
|
||||
}
|
||||
master_ref = mc_id;
|
||||
} else {
|
||||
master_ref = {};
|
||||
}
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ class ShardStateQ : virtual public ShardState {
|
|||
bool before_split_{false};
|
||||
bool fake_split_{false};
|
||||
bool fake_merge_{false};
|
||||
td::optional<BlockIdExt> master_ref;
|
||||
|
||||
protected:
|
||||
friend class Ref<ShardStateQ>;
|
||||
|
@ -80,6 +81,9 @@ class ShardStateQ : virtual public ShardState {
|
|||
LogicalTime get_logical_time() const override {
|
||||
return lt;
|
||||
}
|
||||
td::optional<BlockIdExt> get_master_ref() const override {
|
||||
return master_ref;
|
||||
}
|
||||
td::Status validate_deep() const override;
|
||||
ShardStateQ* make_copy() const override;
|
||||
td::Result<Ref<MessageQueue>> message_queue() const override;
|
||||
|
|
|
@ -972,6 +972,7 @@ bool ValidateQuery::fetch_config_params() {
|
|||
}
|
||||
compute_phase_cfg_.suspended_addresses = config_->get_suspended_addresses(now_);
|
||||
compute_phase_cfg_.size_limits = size_limits;
|
||||
compute_phase_cfg_.precompiled_contracts = config_->get_precompiled_contracts_config();
|
||||
}
|
||||
{
|
||||
// compute action_phase_cfg
|
||||
|
|
|
@ -44,6 +44,7 @@ class ShardState : public td::CntObject {
|
|||
virtual BlockIdExt get_block_id() const = 0;
|
||||
virtual RootHash root_hash() const = 0;
|
||||
virtual td::Ref<vm::Cell> root_cell() const = 0;
|
||||
virtual td::optional<BlockIdExt> get_master_ref() const = 0;
|
||||
|
||||
virtual td::Status validate_deep() const = 0;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue