Skip to content

Commit 0b024a6

Browse files
authored
Improve processing block candidate broadcasts, prepare to broadcast shard blocks without signatures (#1642)
1 parent 413b898 commit 0b024a6

20 files changed

+299
-118
lines changed

create-hardfork/create-hardfork.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,9 @@ class HardforkCreator : public td::actor::Actor {
216216
std::move(msg), 0);
217217
}
218218
for (auto &topmsg : top_shard_descrs_) {
219-
td::actor::send_closure(validator_manager_, &ton::validator::ValidatorManager::new_shard_block, ton::BlockIdExt{},
220-
0, std::move(topmsg));
219+
td::actor::send_closure(validator_manager_,
220+
&ton::validator::ValidatorManager::new_shard_block_description_broadcast,
221+
ton::BlockIdExt{}, 0, std::move(topmsg));
221222
}
222223
class Callback : public ton::validator::ValidatorManagerInterface::Callback {
223224
private:
@@ -246,7 +247,7 @@ class HardforkCreator : public td::actor::Actor {
246247
void send_shard_block_info(ton::BlockIdExt block_id, ton::CatchainSeqno cc_seqno, td::BufferSlice data) override {
247248
}
248249
void send_block_candidate(ton::BlockIdExt block_id, ton::CatchainSeqno cc_seqno, td::uint32 validator_set_hash,
249-
td::BufferSlice data) override {
250+
td::BufferSlice data, int mode) override {
250251
}
251252
void send_broadcast(ton::BlockBroadcast broadcast, int mode) override {
252253
}

tdutils/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ set(TDUTILS_SOURCE
214214
td/utils/invoke.h
215215
td/utils/JsonBuilder.h
216216
td/utils/List.h
217+
td/utils/LRUCache.h
217218
td/utils/logging.h
218219
td/utils/MemoryLog.h
219220
td/utils/misc.h

tdutils/td/utils/LRUCache.h

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
This file is part of TON Blockchain Library.
3+
4+
TON Blockchain Library is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU Lesser General Public License as published by
6+
the Free Software Foundation, either version 2 of the License, or
7+
(at your option) any later version.
8+
9+
TON Blockchain Library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public License
15+
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
#pragma once
18+
19+
#include <set>
20+
#include <memory>
21+
#include "List.h"
22+
#include "check.h"
23+
24+
namespace td {
25+
26+
template <typename K, typename V>
27+
class LRUCache {
28+
public:
29+
explicit LRUCache(size_t max_size) : max_size_(max_size) {
30+
CHECK(max_size_ > 0);
31+
}
32+
LRUCache(const LRUCache&) = delete;
33+
LRUCache& operator=(const LRUCache&) = delete;
34+
35+
V* get_if_exists(const K& key, bool update = true) {
36+
auto it = cache_.find(key);
37+
if (it == cache_.end()) {
38+
return nullptr;
39+
}
40+
Entry* entry = it->get();
41+
if (update) {
42+
entry->remove();
43+
lru_.put(entry);
44+
}
45+
return &entry->value;
46+
}
47+
48+
bool contains(const K& key) const {
49+
return cache_.contains(key);
50+
}
51+
52+
bool put(const K& key, V value, bool update = true) {
53+
bool added = false;
54+
auto it = cache_.find(key);
55+
if (it == cache_.end()) {
56+
update = true;
57+
it = cache_.insert(std::make_unique<Entry>(key, std::move(value))).first;
58+
added = true;
59+
} else {
60+
(*it)->value = std::move(value);
61+
if (update) {
62+
(*it)->remove();
63+
}
64+
}
65+
if (update) {
66+
lru_.put(it->get());
67+
cleanup();
68+
}
69+
return added;
70+
}
71+
72+
V& get(const K& key, bool update = true) {
73+
auto it = cache_.find(key);
74+
if (it == cache_.end()) {
75+
update = true;
76+
it = cache_.insert(std::make_unique<Entry>(key)).first;
77+
} else if (update) {
78+
(*it)->remove();
79+
}
80+
V& result = (*it)->value;
81+
if (update) {
82+
lru_.put(it->get());
83+
cleanup();
84+
}
85+
return result;
86+
}
87+
88+
private:
89+
struct Entry : ListNode {
90+
explicit Entry(K key) : key(std::move(key)) {
91+
}
92+
Entry(K key, V value) : key(std::move(key)), value(std::move(value)) {
93+
}
94+
K key;
95+
V value;
96+
};
97+
struct Cmp {
98+
using is_transparent = void;
99+
bool operator()(const std::unique_ptr<Entry>& a, const std::unique_ptr<Entry>& b) const {
100+
return a->key < b->key;
101+
}
102+
bool operator()(const std::unique_ptr<Entry>& a, const K& b) const {
103+
return a->key < b;
104+
}
105+
bool operator()(const K& a, const std::unique_ptr<Entry>& b) const {
106+
return a < b->key;
107+
}
108+
};
109+
std::set<std::unique_ptr<Entry>, Cmp> cache_;
110+
ListNode lru_;
111+
size_t max_size_;
112+
113+
void cleanup() {
114+
while (cache_.size() > max_size_) {
115+
auto to_remove = (Entry*)lru_.get();
116+
CHECK(to_remove);
117+
to_remove->remove();
118+
cache_.erase(cache_.find(to_remove->key));
119+
}
120+
}
121+
};
122+
123+
} // namespace td

test/test-ton-collator.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,9 @@ class TestNode : public td::actor::Actor {
303303
std::move(msg), 0);
304304
}
305305
for (auto &topmsg : top_shard_descrs_) {
306-
td::actor::send_closure(validator_manager_, &ton::validator::ValidatorManager::new_shard_block, ton::BlockIdExt{},
307-
0, std::move(topmsg));
306+
td::actor::send_closure(validator_manager_,
307+
&ton::validator::ValidatorManager::new_shard_block_description_broadcast,
308+
ton::BlockIdExt{}, 0, std::move(topmsg));
308309
}
309310
class Callback : public ton::validator::ValidatorManagerInterface::Callback {
310311
private:
@@ -347,7 +348,7 @@ class TestNode : public td::actor::Actor {
347348
}
348349
}
349350
void send_block_candidate(ton::BlockIdExt block_id, ton::CatchainSeqno cc_seqno, td::uint32 validator_set_hash,
350-
td::BufferSlice data) override {
351+
td::BufferSlice data, int mode) override {
351352
}
352353
void send_broadcast(ton::BlockBroadcast broadcast, int mode) override {
353354
}

validator/full-node-private-overlay.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ void FullNodePrivateBlockOverlay::process_broadcast(PublicKeyHash src, ton_api::
4949
BlockIdExt block_id = create_block_id(query.block_->block_);
5050
VLOG(FULL_NODE_DEBUG) << "Received newShardBlockBroadcast in private overlay from " << src << ": "
5151
<< block_id.to_str();
52-
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::new_shard_block, block_id,
53-
query.block_->cc_seqno_, std::move(query.block_->data_));
52+
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::new_shard_block_description_broadcast,
53+
block_id, query.block_->cc_seqno_, std::move(query.block_->data_));
5454
}
5555

5656
void FullNodePrivateBlockOverlay::process_broadcast(PublicKeyHash src,

validator/full-node-shard.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -780,8 +780,8 @@ void FullNodeShardImpl::process_broadcast(PublicKeyHash src, ton_api::tonNode_ex
780780
void FullNodeShardImpl::process_broadcast(PublicKeyHash src, ton_api::tonNode_newShardBlockBroadcast &query) {
781781
BlockIdExt block_id = create_block_id(query.block_->block_);
782782
VLOG(FULL_NODE_DEBUG) << "Received newShardBlockBroadcast from " << src << ": " << block_id.to_str();
783-
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::new_shard_block, block_id,
784-
query.block_->cc_seqno_, std::move(query.block_->data_));
783+
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::new_shard_block_description_broadcast,
784+
block_id, query.block_->cc_seqno_, std::move(query.block_->data_));
785785
}
786786

787787
void FullNodeShardImpl::process_broadcast(PublicKeyHash src, ton_api::tonNode_newBlockCandidateBroadcast &query) {

validator/full-node.cpp

+19-17
Original file line numberDiff line numberDiff line change
@@ -313,18 +313,20 @@ void FullNodeImpl::send_shard_block_info(BlockIdExt block_id, CatchainSeqno cc_s
313313
}
314314

315315
void FullNodeImpl::send_block_candidate(BlockIdExt block_id, CatchainSeqno cc_seqno, td::uint32 validator_set_hash,
316-
td::BufferSlice data) {
317-
send_block_candidate_broadcast_to_custom_overlays(block_id, cc_seqno, validator_set_hash, data);
318-
auto shard = get_shard(ShardIdFull{masterchainId, shardIdAll});
319-
if (shard.empty()) {
320-
VLOG(FULL_NODE_WARNING) << "dropping OUT shard block info message to unknown shard";
321-
return;
316+
td::BufferSlice data, int mode) {
317+
if (mode & broadcast_mode_custom) {
318+
send_block_candidate_broadcast_to_custom_overlays(block_id, cc_seqno, validator_set_hash, data);
322319
}
323-
if (!private_block_overlays_.empty()) {
320+
if ((mode & broadcast_mode_private_block) && !private_block_overlays_.empty()) {
324321
td::actor::send_closure(private_block_overlays_.begin()->second, &FullNodePrivateBlockOverlay::send_block_candidate,
325322
block_id, cc_seqno, validator_set_hash, data.clone());
326323
}
327-
if (broadcast_block_candidates_in_public_overlay_) {
324+
if (mode & broadcast_mode_public) {
325+
auto shard = get_shard(ShardIdFull{masterchainId, shardIdAll});
326+
if (shard.empty()) {
327+
VLOG(FULL_NODE_WARNING) << "dropping OUT shard block info message to unknown shard";
328+
return;
329+
}
328330
td::actor::send_closure(shard, &FullNodeShard::send_block_candidate, block_id, cc_seqno, validator_set_hash,
329331
std::move(data));
330332
}
@@ -334,18 +336,18 @@ void FullNodeImpl::send_broadcast(BlockBroadcast broadcast, int mode) {
334336
if (mode & broadcast_mode_custom) {
335337
send_block_broadcast_to_custom_overlays(broadcast);
336338
}
337-
auto shard = get_shard(broadcast.block_id.shard_full());
338-
if (shard.empty()) {
339-
VLOG(FULL_NODE_WARNING) << "dropping OUT broadcast to unknown shard";
340-
return;
341-
}
342339
if (mode & broadcast_mode_private_block) {
343340
if (!private_block_overlays_.empty()) {
344341
td::actor::send_closure(private_block_overlays_.begin()->second, &FullNodePrivateBlockOverlay::send_broadcast,
345342
broadcast.clone());
346343
}
347344
}
348345
if (mode & broadcast_mode_public) {
346+
auto shard = get_shard(broadcast.block_id.shard_full());
347+
if (shard.empty()) {
348+
VLOG(FULL_NODE_WARNING) << "dropping OUT broadcast to unknown shard";
349+
return;
350+
}
349351
td::actor::send_closure(shard, &FullNodeShard::send_broadcast, std::move(broadcast));
350352
}
351353
}
@@ -556,7 +558,7 @@ void FullNodeImpl::send_validator_telemetry(PublicKeyHash key, tl_object_ptr<ton
556558

557559
void FullNodeImpl::process_block_broadcast(BlockBroadcast broadcast) {
558560
send_block_broadcast_to_custom_overlays(broadcast);
559-
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::prevalidate_block, std::move(broadcast),
561+
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::new_block_broadcast, std::move(broadcast),
560562
[](td::Result<td::Unit> R) {
561563
if (R.is_error()) {
562564
if (R.error().code() == ErrorCode::notready) {
@@ -572,7 +574,7 @@ void FullNodeImpl::process_block_candidate_broadcast(BlockIdExt block_id, Catcha
572574
td::uint32 validator_set_hash, td::BufferSlice data) {
573575
send_block_candidate_broadcast_to_custom_overlays(block_id, cc_seqno, validator_set_hash, data);
574576
// ignore cc_seqno and validator_hash for now
575-
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::new_block_candidate, block_id,
577+
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::new_block_candidate_broadcast, block_id,
576578
std::move(data));
577579
}
578580

@@ -630,9 +632,9 @@ void FullNodeImpl::start_up() {
630632
td::actor::send_closure(id_, &FullNodeImpl::send_shard_block_info, block_id, cc_seqno, std::move(data));
631633
}
632634
void send_block_candidate(BlockIdExt block_id, CatchainSeqno cc_seqno, td::uint32 validator_set_hash,
633-
td::BufferSlice data) override {
635+
td::BufferSlice data, int mode) override {
634636
td::actor::send_closure(id_, &FullNodeImpl::send_block_candidate, block_id, cc_seqno, validator_set_hash,
635-
std::move(data));
637+
std::move(data), mode);
636638
}
637639
void send_broadcast(BlockBroadcast broadcast, int mode) override {
638640
td::actor::send_closure(id_, &FullNodeImpl::send_broadcast, std::move(broadcast), mode);

validator/full-node.hpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class FullNodeImpl : public FullNode {
6666
void send_ext_message(AccountIdPrefixFull dst, td::BufferSlice data);
6767
void send_shard_block_info(BlockIdExt block_id, CatchainSeqno cc_seqnp, td::BufferSlice data);
6868
void send_block_candidate(BlockIdExt block_id, CatchainSeqno cc_seqno, td::uint32 validator_set_hash,
69-
td::BufferSlice data);
69+
td::BufferSlice data, int mode);
7070
void send_broadcast(BlockBroadcast broadcast, int mode);
7171
void download_block(BlockIdExt id, td::uint32 priority, td::Timestamp timeout, td::Promise<ReceivedBlock> promise);
7272
void download_zero_state(BlockIdExt id, td::uint32 priority, td::Timestamp timeout,
@@ -144,7 +144,6 @@ class FullNodeImpl : public FullNode {
144144
FullNodeOptions opts_;
145145

146146
std::map<PublicKeyHash, td::actor::ActorOwn<FullNodePrivateBlockOverlay>> private_block_overlays_;
147-
bool broadcast_block_candidates_in_public_overlay_ = false;
148147

149148
struct CustomOverlayInfo {
150149
CustomOverlayParams params_;

validator/impl/accept-block.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,11 @@ void AcceptBlockQuery::applied() {
951951
// do not wait for answer
952952
td::actor::send_closure_later(manager_, &ValidatorManager::send_block_broadcast, std::move(b), send_broadcast_mode_);
953953

954+
// Do this for shard blocks later:
955+
// td::actor::send_closure(manager_, &ValidatorManager::send_block_candidate_broadcast, id_,
956+
// validator_set_->get_catchain_seqno(), validator_set_->get_validator_set_hash(),
957+
// std::move(b.data), send_broadcast_mode_);
958+
954959
finish_query();
955960
}
956961

validator/impl/top-shard-descr.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ class ShardTopBlockDescrQ final : public ShardTopBlockDescrQBase {
7474
std::size_t size() const {
7575
return chain_blk_ids_.size();
7676
}
77+
const std::vector<BlockIdExt>& get_chain_blocks() const override {
78+
return chain_blk_ids_;
79+
}
7780
UnixTime generated_at() const override {
7881
return gen_utime_;
7982
}

validator/interfaces/shard-block.h

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class ShardTopBlockDescription : public td::CntObject {
3535
virtual bool after_split() const = 0;
3636
virtual bool after_merge() const = 0;
3737
virtual CatchainSeqno catchain_seqno() const = 0;
38+
virtual const std::vector<BlockIdExt>& get_chain_blocks() const = 0;
3839
virtual UnixTime generated_at() const = 0;
3940

4041
// if method returns false this shard block description is discarded

validator/interfaces/validator-manager.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class ValidatorManager : public ValidatorManagerInterface {
104104
virtual void set_block_candidate(BlockIdExt id, BlockCandidate candidate, CatchainSeqno cc_seqno,
105105
td::uint32 validator_set_hash, td::Promise<td::Unit> promise) = 0;
106106
virtual void send_block_candidate_broadcast(BlockIdExt id, CatchainSeqno cc_seqno, td::uint32 validator_set_hash,
107-
td::BufferSlice data) = 0;
107+
td::BufferSlice data, int mode) = 0;
108108

109109
virtual void wait_block_state_merge(BlockIdExt left_id, BlockIdExt right_id, td::uint32 priority,
110110
td::Timestamp timeout, td::Promise<td::Ref<ShardState>> promise) = 0;

validator/manager-disk.cpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ void ValidatorManagerImpl::validate_block(ReceivedBlock block, td::Promise<Block
6464
UNREACHABLE();
6565
}
6666

67-
void ValidatorManagerImpl::prevalidate_block(BlockBroadcast broadcast, td::Promise<td::Unit> promise) {
67+
void ValidatorManagerImpl::new_block_broadcast(BlockBroadcast broadcast, td::Promise<td::Unit> promise) {
6868
UNREACHABLE();
6969
}
7070

@@ -276,7 +276,8 @@ void ValidatorManagerImpl::new_ihr_message(td::BufferSlice data) {
276276
}
277277
}
278278

279-
void ValidatorManagerImpl::new_shard_block(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) {
279+
void ValidatorManagerImpl::new_shard_block_description_broadcast(BlockIdExt block_id, CatchainSeqno cc_seqno,
280+
td::BufferSlice data) {
280281
if (!last_masterchain_block_handle_) {
281282
shard_blocks_raw_.push_back(std::move(data));
282283
return;
@@ -528,7 +529,7 @@ void ValidatorManagerImpl::get_shard_blocks(BlockIdExt masterchain_block_id,
528529
}
529530
if (!shard_blocks_raw_.empty()) {
530531
for (auto &raw : shard_blocks_raw_) {
531-
new_shard_block(BlockIdExt{}, 0, std::move(raw));
532+
new_shard_block_description_broadcast(BlockIdExt{}, 0, std::move(raw));
532533
}
533534
shard_blocks_raw_.clear();
534535
}
@@ -786,8 +787,9 @@ void ValidatorManagerImpl::set_block_candidate(BlockIdExt id, BlockCandidate can
786787
}
787788

788789
void ValidatorManagerImpl::send_block_candidate_broadcast(BlockIdExt id, CatchainSeqno cc_seqno,
789-
td::uint32 validator_set_hash, td::BufferSlice data) {
790-
callback_->send_block_candidate(id, cc_seqno, validator_set_hash, std::move(data));
790+
td::uint32 validator_set_hash, td::BufferSlice data,
791+
int mode) {
792+
callback_->send_block_candidate(id, cc_seqno, validator_set_hash, std::move(data), mode);
791793
}
792794

793795
void ValidatorManagerImpl::write_handle(BlockHandle handle, td::Promise<td::Unit> promise) {
@@ -947,7 +949,7 @@ void ValidatorManagerImpl::update_shard_blocks() {
947949
}
948950
if (!shard_blocks_raw_.empty()) {
949951
for (auto &raw : shard_blocks_raw_) {
950-
new_shard_block(BlockIdExt{}, 0, std::move(raw));
952+
new_shard_block_description_broadcast(BlockIdExt{}, 0, std::move(raw));
951953
}
952954
shard_blocks_raw_.clear();
953955
}

0 commit comments

Comments
 (0)