Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions crypto/block/block.tlb
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ block_info#9bc7a987 version:uint32
after_split:(## 1)
want_split:Bool want_merge:Bool
key_block:Bool vert_seqno_incr:(## 1)
flags:(## 8) { flags <= 1 }
flags:(## 8) { flags <= 3 }
seq_no:# vert_seq_no:# { vert_seq_no >= vert_seqno_incr }
{ prev_seq_no:# } { ~prev_seq_no + 1 = seq_no }
shard:ShardIdent gen_utime:uint32
Expand All @@ -464,6 +464,7 @@ block_info#9bc7a987 version:uint32
master_ref:not_master?^BlkMasterInfo
prev_ref:^(BlkPrevInfo after_merge)
prev_vert_ref:vert_seqno_incr?^(BlkPrevInfo 0)
collated_data_hash:flags . 1?bits256
= BlockInfo;

prev_blk_info$_ prev:ExtBlkRef = BlkPrevInfo 0;
Expand Down Expand Up @@ -772,7 +773,7 @@ consensus_config_v3#d8 flags:(## 7) { flags = 0 } new_catchain_ids:Bool
max_block_bytes:uint32 max_collated_bytes:uint32
proto_version:uint16 = ConsensusConfig;

consensus_config_v4#d9 flags:(## 7) { flags = 0 } new_catchain_ids:Bool
consensus_config_v4#d9 flags:(## 6) { flags = 0 } merge_collated_data:Bool new_catchain_ids:Bool
round_candidates:(## 8) { round_candidates >= 1 }
next_candidate_delay_ms:uint32 consensus_timeout_ms:uint32
fast_attempts:uint32 attempt_duration:uint32 catchain_max_deps:uint32
Expand Down Expand Up @@ -857,6 +858,9 @@ top_block_descr#d5 proof_for:BlockIdExt signatures:(Maybe ^BlockSignatures)
//
top_block_descr_set#4ac789f3 collection:(HashmapE 96 ^TopBlockDescr) = TopBlockDescrSet;
account_storage_dict_proof#37c1e3fc proof:^Cell = AccountStorageDictProof;
collated_data_root_state#4b2f36ec hash:bits256 = CollatedDataRootState;
collated_data_root_storage_dict#796eaeb6 hash:bits256 = CollatedDataRootStorageDict;
collated_data_separator#fa8b2b92 = CollatedDataSeparator;

//
// VALIDATOR MISBEHAVIOR COMPLAINTS
Expand Down
1 change: 1 addition & 0 deletions crypto/block/mc-config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ ton::ValidatorSessionConfig Config::get_consensus_config() const {
td::uint64 catchain_lifetime = std::max(catchain_config.mc_cc_lifetime, catchain_config.shard_cc_lifetime);
c.catchain_opts.max_block_height_coeff = catchain_lifetime * max_blocks_coeff;
}
c.merge_collated_data = r.merge_collated_data;
};
if (cc.not_null()) {
block::gen::ConsensusConfig::Record_consensus_config_v4 r4;
Expand Down
6 changes: 3 additions & 3 deletions crypto/common/refcnt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,14 +285,14 @@ class Ref {
Ref& operator=(Ref<S>&& r);
const typename RefValue<T>::Type* operator->() const {
if (!ptr) {
CHECK(ptr && "deferencing null Ref");
LOG_CHECK(ptr) << "dereferencing null Ref<" << typeid(T).name() << ">";
throw NullRef{};
}
return RefValue<T>::make_const_ptr(ptr);
}
const typename RefValue<T>::Type& operator*() const {
if (!ptr) {
CHECK(ptr && "deferencing null Ref");
LOG_CHECK(ptr) << "dereferencing null Ref<" << typeid(T).name() << ">";
throw NullRef{};
}
return RefValue<T>::make_const_ref(ptr);
Expand All @@ -308,7 +308,7 @@ class Ref {
}
bool is_unique() const {
if (!ptr) {
CHECK(ptr && "defererencing null Ref");
LOG_CHECK(ptr) << "dereferencing null Ref<" << typeid(T).name() << ">";
throw NullRef{};
}
return ptr->is_unique();
Expand Down
3 changes: 2 additions & 1 deletion crypto/vm/boc-compression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "td/utils/Slice-decl.h"
#include "td/utils/lz4.h"
#include "ton/ton-types.h"
#include "vm/boc-writers.h"
#include "vm/boc.h"
#include "vm/cells.h"
Expand Down Expand Up @@ -59,7 +60,7 @@ td::Result<std::vector<td::Ref<vm::Cell>>> boc_decompress_baseline_lz4(td::Slice
}

TRY_RESULT(decompressed, td::lz4_decompress(compressed, decompressed_size));
TRY_RESULT(roots, vm::std_boc_deserialize_multi(decompressed));
TRY_RESULT(roots, vm::std_boc_deserialize_multi(decompressed, ton::max_collated_data_roots + 1, true));
return roots;
}

Expand Down
119 changes: 99 additions & 20 deletions crypto/vm/boc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include <iomanip>
#include <iostream>

#include "cells/MerkleProof.h"
#include "cells/PrunnedCell.h"
#include "td/utils/Slice-decl.h"
#include "td/utils/bits.h"
#include "td/utils/crypto.h"
Expand Down Expand Up @@ -974,7 +976,7 @@ td::Result<Ref<Cell>> std_boc_deserialize(td::Slice data, bool can_be_empty, boo
return std::move(root);
}

td::Result<std::vector<Ref<Cell>>> std_boc_deserialize_multi(td::Slice data, int max_roots) {
td::Result<std::vector<Ref<Cell>>> std_boc_deserialize_multi(td::Slice data, int max_roots, bool allow_nonzero_level) {
if (data.empty()) {
return std::vector<Ref<Cell>>{};
}
Expand All @@ -990,7 +992,7 @@ td::Result<std::vector<Ref<Cell>>> std_boc_deserialize_multi(td::Slice data, int
if (root.is_null()) {
return td::Status::Error("bag of cells has a null root cell (?)");
}
if (root->get_level() != 0) {
if (!allow_nonzero_level && root->get_level() != 0) {
return td::Status::Error("bag of cells has a root with non-zero level");
}
roots.emplace_back(std::move(root));
Expand Down Expand Up @@ -1266,35 +1268,36 @@ bool VmStorageStat::add_storage(const CellSlice& cs) {
}

void ProofStorageStat::add_loaded_cell(const Ref<DataCell>& cell, td::uint8 max_level) {
max_level = std::min<td::uint32>(max_level, Cell::max_level);
auto& [status, size] = cells_[cell->get_hash(max_level)];
if (status == c_loaded) {
max_level = std::min<td::uint8>(max_level, Cell::max_level);
auto& info = cells_[cell->get_hash(max_level)];
if (info.status == c_loaded) {
return;
}
proof_size_ -= size;
status = c_loaded;
proof_size_ += size = estimate_serialized_size(cell);
proof_size_ -= info.serialized_size;
info.status = c_loaded;
info.cell = cell;
info.cell_max_level = max_level;
proof_size_ += info.serialized_size = estimate_serialized_size(cell);
max_level += (cell->special_type() == CellTraits::SpecialType::MerkleProof ||
cell->special_type() == CellTraits::SpecialType::MerkleUpdate);
for (unsigned i = 0; i < cell->size_refs(); ++i) {
auto& [child_status, child_size] = cells_[cell->get_ref(i)->get_hash(max_level)];
if (child_status == c_none) {
child_status = c_prunned;
proof_size_ += child_size = estimate_prunned_size();
auto& child = cells_[cell->get_ref(i)->get_hash(max_level)];
if (child.status == c_none) {
child.status = c_prunned;
proof_size_ += child.serialized_size = estimate_prunned_size();
}
}
}

void ProofStorageStat::add_loaded_cells(const ProofStorageStat& other) {
for (const auto& [hash, x] : other.cells_) {
const auto& [new_status, new_size] = x;
auto& [old_status, old_size] = cells_[hash];
if (old_status >= new_status) {
for (const auto& [hash, new_info] : other.cells_) {
auto& old_info = cells_[hash];
if (old_info.status >= new_info.status) {
continue;
}
proof_size_ -= old_size;
old_status = new_status;
proof_size_ += old_size = new_size;
proof_size_ -= old_info.serialized_size;
old_info = new_info;
proof_size_ += old_info.serialized_size;
}
}

Expand All @@ -1304,7 +1307,83 @@ td::uint64 ProofStorageStat::estimate_proof_size() const {

ProofStorageStat::CellStatus ProofStorageStat::get_cell_status(const Cell::Hash& hash) const {
auto it = cells_.find(hash);
return it == cells_.end() ? c_none : it->second.first;
return it == cells_.end() ? c_none : it->second.status;
}

std::vector<Ref<Cell>> ProofStorageStat::build_collated_data(std::vector<Ref<Cell>> skip_roots) const {
struct Cache {
Ref<Cell> result;
bool is_root = true;
bool skip = false;
bool skip_visited = false;
};
std::map<Cell::Hash, Cache> cache;

std::function<void(const Ref<Cell>&)> dfs_skip = [&](const Ref<Cell>& cell) {
Cell::Hash hash = cell->get_hash();
Cache& entry = cache[hash];
if (entry.skip_visited) {
return;
}
entry.skip_visited = entry.skip = true;
CellSlice cs{NoVm{}, cell};
if (cs.special_type() != CellTraits::SpecialType::PrunnedBranch) {
for (unsigned i = 0; i < cell->get_level(); ++i) {
cache[cell->get_hash(i)].skip = true;
}
}
for (unsigned i = 0; i < cs.size_refs(); ++i) {
dfs_skip(cs.prefetch_ref(i));
}
};
for (const auto& cell : skip_roots) {
if (cell.not_null()) {
dfs_skip(cell);
}
}

std::function<Cache&(const CellInfo&)> dfs = [&](const CellInfo& info) -> Cache& {
Cell::Hash hash = info.cell->get_hash(info.cell_max_level);
Cache& entry = cache[hash];
if (entry.result.not_null()) {
return entry;
}
CellBuilder cb;
cb.store_bits(info.cell->get_data(), info.cell->size());
td::uint8 child_max_level = info.cell_max_level;
if (info.cell->special_type() == CellTraits::SpecialType::MerkleProof ||
info.cell->special_type() == CellTraits::SpecialType::MerkleUpdate) {
++child_max_level;
}
for (unsigned i = 0; i < info.cell->size_refs(); ++i) {
Ref<Cell> child = info.cell->get_ref(i);
Cell::Hash child_hash = child->get_hash(child_max_level);
auto it = cells_.find(child_hash);
if (it == cells_.end() || it->second.status != c_loaded || cache[child_hash].skip) {
cb.store_ref(CellBuilder::create_pruned_branch(child, Cell::max_level, child_max_level));
} else {
Cache& child_result = dfs(it->second);
child_result.is_root = false;
cb.store_ref(child_result.result);
}
}
Cache& entry2 = cache[hash];
entry2.result = cb.finalize(info.cell->is_special());
CHECK(entry2.result->get_hash(std::min<int>(info.cell->get_level(), info.cell_max_level)) == hash);
return entry2;
};
for (auto& [hash, info] : cells_) {
if (info.status == c_loaded && !cache[hash].skip) {
dfs(info);
}
}
std::vector<Ref<Cell>> result;
for (auto& [_, entry] : cache) {
if (entry.result.not_null() && entry.is_root) {
result.push_back(std::move(entry.result));
}
}
return result;
}

td::uint64 ProofStorageStat::estimate_prunned_size() {
Expand Down
13 changes: 11 additions & 2 deletions crypto/vm/boc.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,19 @@ class ProofStorageStat {
return get_cell_status(hash) == c_loaded;
}

std::vector<Ref<Cell>> build_collated_data(std::vector<Ref<Cell>> skip_roots = {}) const;

static td::uint64 estimate_prunned_size();
static td::uint64 estimate_serialized_size(const Ref<DataCell>& cell);

private:
td::HashMap<Cell::Hash, std::pair<CellStatus, td::uint64>> cells_;
struct CellInfo {
Ref<DataCell> cell; // only for c_loaded
td::uint8 cell_max_level = Cell::max_level; // only for c_loaded
CellStatus status = c_none;
td::uint64 serialized_size = 0;
};
td::HashMap<Cell::Hash, CellInfo> cells_;
td::uint64 proof_size_ = 0;
};

Expand Down Expand Up @@ -402,7 +410,8 @@ td::Result<Ref<Cell>> std_boc_deserialize(td::Slice data, bool can_be_empty = fa
td::Result<td::BufferSlice> std_boc_serialize(Ref<Cell> root, int mode = 0);

td::Result<std::vector<Ref<Cell>>> std_boc_deserialize_multi(td::Slice data,
int max_roots = BagOfCells::default_max_roots);
int max_roots = BagOfCells::default_max_roots,
bool allow_nonzero_level = false);
td::Result<td::BufferSlice> std_boc_serialize_multi(std::vector<Ref<Cell>> root, int mode = 0);

td::Status std_boc_serialize_to_file(Ref<Cell> root, td::FileFd& fd, int mode = 0,
Expand Down
12 changes: 12 additions & 0 deletions crypto/vm/cells/ExtCell.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ class ExtCell : public Cell {
Ref<PrunnedCell<ExtraT>> get_prunned_cell() const {
return prunned_cell_.load();
}
td::Status set_inner_cell(Ref<DataCell> new_cell) const {
auto prunned_cell = prunned_cell_.load();
if (prunned_cell.is_null()) {
return td::Status::OK();
}
TRY_STATUS(prunned_cell->check_equals_unloaded(new_cell));
if (data_cell_.store_if_empty(new_cell)) {
prunned_cell_.store({});
get_thread_safe_counter_unloaded().add(-1);
}
return td::Status::OK();
}

private:
mutable td::AtomicRef<DataCell> data_cell_;
Expand Down
8 changes: 6 additions & 2 deletions overlay/overlay-peers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,12 +510,16 @@ void OverlayImpl::get_overlay_random_peers(td::uint32 max_peers,
td::Promise<std::vector<adnl::AdnlNodeIdShort>> promise) {
std::vector<adnl::AdnlNodeIdShort> v;
auto t = td::Clocks::system();
while (v.size() < max_peers && v.size() < peer_list_.peers_.size() - peer_list_.bad_peers_.size()) {
td::uint32 iters = 0;
while (v.size() < max_peers && v.size() < peer_list_.peers_.size() - peer_list_.bad_peers_.size() &&
iters <= peer_list_.peers_.size() * 2) {
++iters;
auto P = peer_list_.peers_.get_random();
if (!P->is_permanent_member() && (P->get_version() + 3600 < t || P->certificate()->is_expired(t))) {
VLOG(OVERLAY_INFO) << this << ": deleting outdated peer " << P->get_id();
del_peer(P->get_id());
} else if (P->is_alive()) {
} else if (P->is_alive() && P->get_id() != local_id_ &&
!(P->get_node()->flags() & OverlayMemberFlags::DoNotReceiveBroadcasts)) {
bool dup = false;
for (auto &n : v) {
if (n == P->get_id()) {
Expand Down
10 changes: 10 additions & 0 deletions tdutils/td/utils/LRUCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ class LRUCache {
return result;
}

void remove(const K& key) {
auto it = cache_.find(key);
if (it == cache_.end()) {
return;
}
total_weight_ -= (*it)->weight;
(*it)->remove();
cache_.erase(it);
}

private:
struct Entry : ListNode {
Entry(K key, uint64 weight) : key(std::move(key)), weight(weight) {
Expand Down
4 changes: 2 additions & 2 deletions tdutils/td/utils/Status.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
#define TRY_RESULT_ASSIGN(name, result) TRY_RESULT_IMPL(TD_CONCAT(r_response, __LINE__), name, result)

#define TRY_RESULT_PROMISE_ASSIGN(promise_name, name, result) \
TRY_RESULT_PROMISE_IMPL(promise_name, TD_CONCAT(TD_CONCAT(r_, name), __LINE__), name, result)
TRY_RESULT_PROMISE_IMPL(promise_name, TD_CONCAT(r_response, __LINE__), name, result)

#define TRY_RESULT_PREFIX(name, result, prefix) \
TRY_RESULT_PREFIX_IMPL(TD_CONCAT(TD_CONCAT(r_, name), __LINE__), auto name, result, prefix)
Expand All @@ -86,7 +86,7 @@
TRY_RESULT_PROMISE_PREFIX_IMPL(promise_name, TD_CONCAT(TD_CONCAT(r_, name), __LINE__), auto name, result, prefix)

#define TRY_RESULT_PROMISE_PREFIX_ASSIGN(promise_name, name, result, prefix) \
TRY_RESULT_PROMISE_PREFIX_IMPL(promise_name, TD_CONCAT(TD_CONCAT(r_, name), __LINE__), name, result, prefix)
TRY_RESULT_PROMISE_PREFIX_IMPL(promise_name, TD_CONCAT(r_response, __LINE__), name, result, prefix)

#define TRY_RESULT_IMPL(r_name, name, result) \
auto r_name = (result); \
Expand Down
7 changes: 7 additions & 0 deletions tdutils/td/utils/optional.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ class optional {
return {};
}

td::optional<T> clone() const {
if (*this) {
return value().clone();
}
return {};
}

template <class... ArgsT>
void emplace(ArgsT &&...args) {
impl_.emplace(std::forward<ArgsT>(args)...);
Expand Down
Loading
Loading