Skip to content

Commit cac968f

Browse files
authored
Merge pull request #1761 from ton-blockchain/testnet
Merge developer branch
2 parents dfda879 + 8a971be commit cac968f

File tree

103 files changed

+8686
-1181
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+8686
-1181
lines changed

Changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2025.07 Accelerator Update
2+
3+
Separation of validation and collation processes that allows to host them on independent machines and achieve full horizontal scaling. [More details in documentation](https://docs.ton.org/v3/documentation/infra/nodes/validation/collators)
4+
15
## 2025.06 Update
26

37
1. ADNL and candidate broadcast optimization

adnl/adnl-node-id.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ class AdnlNodeIdShort {
3737
}
3838
explicit AdnlNodeIdShort(td::Bits256 value) : hash_(value) {
3939
}
40-
explicit AdnlNodeIdShort(tl_object_ptr<ton_api::adnl_id_short> obj) : hash_(obj->id_) {
40+
explicit AdnlNodeIdShort(tl_object_ptr<ton_api::adnl_id_short> &&obj) : hash_(obj->id_) {
41+
}
42+
explicit AdnlNodeIdShort(const tl_object_ptr<ton_api::adnl_id_short> &obj) : hash_(obj->id_) {
4143
}
4244

4345
const auto &pubkey_hash() const {

crypto/block/block.cpp

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -676,10 +676,25 @@ bool ParamLimits::deserialize(vm::CellSlice& cs) {
676676
}
677677

678678
bool BlockLimits::deserialize(vm::CellSlice& cs) {
679-
return cs.fetch_ulong(8) == 0x5d // block_limits#5d
680-
&& bytes.deserialize(cs) // bytes:ParamLimits
681-
&& gas.deserialize(cs) // gas:ParamLimits
682-
&& lt_delta.deserialize(cs); // lt_delta:ParamLimits
679+
auto tag = cs.fetch_ulong(8);
680+
if (tag != 0x5d && tag != 0x5e) {
681+
return false;
682+
}
683+
// block_limits#5d
684+
// block_limits_v2#5e
685+
bool ok = bytes.deserialize(cs) // bytes:ParamLimits
686+
&& gas.deserialize(cs) // gas:ParamLimits
687+
&& lt_delta.deserialize(cs); // lt_delta:ParamLimits
688+
if (!ok) {
689+
return false;
690+
}
691+
if (tag == 0x5e) {
692+
return collated_data.deserialize(cs) && // collated_data:ParamLimits
693+
imported_msg_queue.deserialize(cs); // imported_msg_queue:ImportedMsgQueueLimits
694+
} else {
695+
collated_data = bytes;
696+
return true;
697+
}
683698
}
684699

685700
int ParamLimits::classify(td::uint64 value) const {
@@ -711,12 +726,19 @@ int BlockLimits::classify_lt(ton::LogicalTime lt) const {
711726
return lt_delta.classify(lt - start_lt);
712727
}
713728

714-
int BlockLimits::classify(td::uint64 size, td::uint64 gas, ton::LogicalTime lt) const {
715-
return std::max(std::max(classify_size(size), classify_gas(gas)), classify_lt(lt));
729+
int BlockLimits::classify_collated_data_size(td::uint64 size) const {
730+
return collated_data.classify(size);
731+
}
732+
733+
int BlockLimits::classify(td::uint64 size, td::uint64 gas, ton::LogicalTime lt, td::uint64 collated_size) const {
734+
return std::max(
735+
{classify_size(size), classify_gas(gas), classify_lt(lt), classify_collated_data_size(collated_size)});
716736
}
717737

718-
bool BlockLimits::fits(unsigned cls, td::uint64 size, td::uint64 gas_value, ton::LogicalTime lt) const {
719-
return bytes.fits(cls, size) && gas.fits(cls, gas_value) && lt_delta.fits(cls, lt - start_lt);
738+
bool BlockLimits::fits(unsigned cls, td::uint64 size, td::uint64 gas_value, ton::LogicalTime lt,
739+
td::uint64 collated_size) const {
740+
return bytes.fits(cls, size) && gas.fits(cls, gas_value) && lt_delta.fits(cls, lt - start_lt) &&
741+
collated_data.fits(cls, collated_size);
720742
}
721743

722744
td::uint64 BlockLimitStatus::estimate_block_size(const vm::NewCellStorageStat::Stat* extra) const {
@@ -729,20 +751,30 @@ td::uint64 BlockLimitStatus::estimate_block_size(const vm::NewCellStorageStat::S
729751
}
730752

731753
int BlockLimitStatus::classify() const {
732-
return limits.classify(estimate_block_size(), gas_used, cur_lt);
754+
return limits.classify(estimate_block_size(), gas_used, cur_lt, collated_data_size_estimate);
733755
}
734756

735757
bool BlockLimitStatus::fits(unsigned cls) const {
736758
return cls >= ParamLimits::limits_cnt ||
737759
(limits.gas.fits(cls, gas_used) && limits.lt_delta.fits(cls, cur_lt - limits.start_lt) &&
738-
limits.bytes.fits(cls, estimate_block_size()));
760+
limits.bytes.fits(cls, estimate_block_size()) && limits.collated_data.fits(cls, collated_data_size_estimate));
739761
}
740762

741763
bool BlockLimitStatus::would_fit(unsigned cls, ton::LogicalTime end_lt, td::uint64 more_gas,
742764
const vm::NewCellStorageStat::Stat* extra) const {
743765
return cls >= ParamLimits::limits_cnt || (limits.gas.fits(cls, gas_used + more_gas) &&
744766
limits.lt_delta.fits(cls, std::max(cur_lt, end_lt) - limits.start_lt) &&
745-
limits.bytes.fits(cls, estimate_block_size(extra)));
767+
limits.bytes.fits(cls, estimate_block_size(extra)) &&
768+
limits.collated_data.fits(cls, collated_data_size_estimate));
769+
}
770+
771+
double BlockLimitStatus::load_fraction(unsigned cls) const {
772+
if (cls >= ParamLimits::limits_cnt) {
773+
return 0.0;
774+
}
775+
return std::max({(double)estimate_block_size() / (double)limits.bytes.limit(cls),
776+
(double)gas_used / (double)limits.gas.limit(cls),
777+
(double)collated_data_size_estimate / (double)limits.collated_data.limit(cls)});
746778
}
747779

748780
// SETS: account_dict, shard_libraries_, mc_state_extra

crypto/block/block.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ static inline std::ostream& operator<<(std::ostream& os, const MsgProcessedUptoC
219219
struct ImportedMsgQueueLimits {
220220
// Default values
221221
td::uint32 max_bytes = 1 << 16;
222-
td::uint32 max_msgs = 30;
222+
td::uint32 max_msgs = 100;
223223
bool deserialize(vm::CellSlice& cs);
224224
ImportedMsgQueueLimits operator*(td::uint32 x) const {
225225
return {max_bytes * x, max_msgs * x};
@@ -242,6 +242,9 @@ struct ParamLimits {
242242
td::uint32 hard() const {
243243
return limits_[3];
244244
}
245+
td::uint32 limit(unsigned cls) const {
246+
return limits_[cls];
247+
}
245248
bool compute_medium_limit() {
246249
limits_[2] = soft() + ((hard() - soft()) >> 1);
247250
return true;
@@ -261,15 +264,17 @@ struct ParamLimits {
261264
};
262265

263266
struct BlockLimits {
264-
ParamLimits bytes, gas, lt_delta;
267+
ParamLimits bytes, gas, lt_delta, collated_data;
265268
ton::LogicalTime start_lt{0};
269+
ImportedMsgQueueLimits imported_msg_queue;
266270
const vm::CellUsageTree* usage_tree{nullptr};
267271
bool deserialize(vm::CellSlice& cs);
268272
int classify_size(td::uint64 size) const;
269273
int classify_gas(td::uint64 gas) const;
270274
int classify_lt(ton::LogicalTime lt) const;
271-
int classify(td::uint64 size, td::uint64 gas, ton::LogicalTime lt) const;
272-
bool fits(unsigned cls, td::uint64 size, td::uint64 gas, ton::LogicalTime lt) const;
275+
int classify_collated_data_size(td::uint64 size) const;
276+
int classify(td::uint64 size, td::uint64 gas, ton::LogicalTime lt, td::uint64 collated_size) const;
277+
bool fits(unsigned cls, td::uint64 size, td::uint64 gas, ton::LogicalTime lt, td::uint64 collated_size) const;
273278
};
274279

275280
struct BlockLimitStatus {
@@ -278,6 +283,7 @@ struct BlockLimitStatus {
278283
td::uint64 gas_used{};
279284
vm::NewCellStorageStat st_stat;
280285
unsigned accounts{}, transactions{}, extra_out_msgs{};
286+
td::uint64 collated_data_size_estimate = 0;
281287
unsigned public_library_diff{};
282288
BlockLimitStatus(const BlockLimits& limits_, ton::LogicalTime lt = 0)
283289
: limits(limits_), cur_lt(std::max(limits_.start_lt, lt)) {
@@ -289,12 +295,14 @@ struct BlockLimitStatus {
289295
gas_used = 0;
290296
extra_out_msgs = 0;
291297
public_library_diff = 0;
298+
collated_data_size_estimate = 0;
292299
}
293300
td::uint64 estimate_block_size(const vm::NewCellStorageStat::Stat* extra = nullptr) const;
294301
int classify() const;
295302
bool fits(unsigned cls) const;
296303
bool would_fit(unsigned cls, ton::LogicalTime end_lt, td::uint64 more_gas,
297304
const vm::NewCellStorageStat::Stat* extra = nullptr) const;
305+
double load_fraction(unsigned cls) const;
298306
bool add_cell(Ref<vm::Cell> cell) {
299307
st_stat.add_cell(std::move(cell));
300308
return true;

crypto/block/block.tlb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,9 +716,13 @@ config_gas_prices#_ GasLimitsPrices = ConfigParam 21;
716716

717717
param_limits#c3 underload:# soft_limit:# { underload <= soft_limit }
718718
hard_limit:# { soft_limit <= hard_limit } = ParamLimits;
719+
imported_msg_queue_limits#d3 max_bytes:# max_msgs:# = ImportedMsgQueueLimits;
719720
block_limits#5d bytes:ParamLimits gas:ParamLimits lt_delta:ParamLimits
720721
= BlockLimits;
721-
722+
block_limits_v2#5e bytes:ParamLimits gas:ParamLimits lt_delta:ParamLimits
723+
collated_data:ParamLimits imported_msg_queue:ImportedMsgQueueLimits
724+
= BlockLimits;
725+
722726
config_mc_block_limits#_ BlockLimits = ConfigParam 22;
723727
config_block_limits#_ BlockLimits = ConfigParam 23;
724728

@@ -842,6 +846,7 @@ top_block_descr#d5 proof_for:BlockIdExt signatures:(Maybe ^BlockSignatures)
842846
// COLLATED DATA
843847
//
844848
top_block_descr_set#4ac789f3 collection:(HashmapE 96 ^TopBlockDescr) = TopBlockDescrSet;
849+
account_storage_dict_proof#37c1e3fc proof:^Cell = AccountStorageDictProof;
845850

846851
//
847852
// VALIDATOR MISBEHAVIOR COMPLAINTS

crypto/block/mc-config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,11 @@ struct PrecompiledContractsConfig {
546546
td::optional<Contract> get_contract(td::Bits256 code_hash) const;
547547
};
548548

549+
struct CollatorNodeDescr {
550+
ton::ShardIdFull shard;
551+
ton::NodeIdShort adnl_id;
552+
};
553+
549554
class Config {
550555
enum {
551556
default_mc_catchain_lifetime = 200,

crypto/block/output-queue-merger.cpp

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -134,31 +134,22 @@ bool OutputQueueMerger::MsgKeyValue::split(MsgKeyValue& second) {
134134
return true;
135135
}
136136

137-
bool OutputQueueMerger::add_root(int src, Ref<vm::Cell> outmsg_root) {
137+
void OutputQueueMerger::add_root(int src, Ref<vm::Cell> outmsg_root, td::int32 msg_limit) {
138138
if (outmsg_root.is_null()) {
139-
return true;
139+
return;
140140
}
141141
auto kv = std::make_unique<MsgKeyValue>(src, std::move(outmsg_root));
142142
if (kv->replace_by_prefix(common_pfx.cbits(), common_pfx_len)) {
143143
heap.push_back(std::move(kv));
144144
}
145-
return true;
146-
}
147-
148-
OutputQueueMerger::OutputQueueMerger(ton::ShardIdFull _queue_for, std::vector<Neighbor> _neighbors)
149-
: queue_for(_queue_for), neighbors(std::move(_neighbors)), eof(false), failed(false) {
150-
init();
151-
}
152-
153-
OutputQueueMerger::OutputQueueMerger(ton::ShardIdFull _queue_for, std::vector<block::McShardDescr> _neighbors)
154-
: queue_for(_queue_for), eof(false), failed(false) {
155-
for (auto& nb : _neighbors) {
156-
neighbors.emplace_back(nb.top_block_id(), nb.outmsg_root, nb.is_disabled());
145+
if ((int)src_remaining_msgs_.size() < src + 1) {
146+
src_remaining_msgs_.resize(src + 1);
157147
}
158-
init();
148+
src_remaining_msgs_[src] = msg_limit;
159149
}
160150

161-
void OutputQueueMerger::init() {
151+
OutputQueueMerger::OutputQueueMerger(ton::ShardIdFull queue_for, std::vector<OutputQueueMerger::Neighbor> neighbors)
152+
: eof(false), failed(false) {
162153
common_pfx.bits().store_int(queue_for.workchain, 32);
163154
int l = queue_for.pfx_len();
164155
td::bitstring::bits_store_long_top(common_pfx.bits() + 32, queue_for.shard, l);
@@ -168,7 +159,7 @@ void OutputQueueMerger::init() {
168159
if (!neighbor.disabled_) {
169160
LOG(DEBUG) << "adding " << (neighbor.outmsg_root_.is_null() ? "" : "non-") << "empty output queue for neighbor #"
170161
<< i << " (" << neighbor.block_id_.to_str() << ")";
171-
add_root(i++, neighbor.outmsg_root_);
162+
add_root(i++, neighbor.outmsg_root_, neighbor.msg_limit_);
172163
} else {
173164
LOG(DEBUG) << "skipping output queue for disabled neighbor #" << i;
174165
i++;
@@ -222,7 +213,18 @@ bool OutputQueueMerger::load() {
222213
heap.pop_back();
223214
} while (!heap.empty() && heap[0]->lt <= lt);
224215
std::sort(msg_list.begin() + orig_size, msg_list.end(), MsgKeyValue::less);
225-
return true;
216+
for (size_t i = orig_size; i < msg_list.size(); ++i) {
217+
td::int32 &remaining = src_remaining_msgs_[msg_list[i]->source];
218+
if (remaining != -1) {
219+
if (remaining == 0) {
220+
limit_exceeded = true;
221+
} else {
222+
--remaining;
223+
}
224+
}
225+
msg_list[i]->limit_exceeded = limit_exceeded;
226+
}
227+
return msg_list.size() > orig_size;
226228
}
227229

228230
} // namespace block

crypto/block/output-queue-merger.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct OutputQueueMerger {
3232
int source;
3333
int key_len{0};
3434
td::BitArray<max_key_len> key;
35+
bool limit_exceeded{false};
3536
MsgKeyValue() = default;
3637
MsgKeyValue(int src, Ref<vm::Cell> node);
3738
MsgKeyValue(td::ConstBitPtr key_pfx, int key_pfx_len, int src, Ref<vm::Cell> node);
@@ -51,23 +52,22 @@ struct OutputQueueMerger {
5152
bool unpack_node(td::ConstBitPtr key_pfx, int key_pfx_len, Ref<vm::Cell> node);
5253
bool split(MsgKeyValue& second);
5354
};
55+
//
56+
std::vector<std::unique_ptr<MsgKeyValue>> msg_list;
57+
58+
public:
5459
struct Neighbor {
5560
ton::BlockIdExt block_id_;
5661
td::Ref<vm::Cell> outmsg_root_;
5762
bool disabled_;
63+
td::int32 msg_limit_; // -1 - unlimited
5864
Neighbor() = default;
59-
Neighbor(ton::BlockIdExt block_id, td::Ref<vm::Cell> outmsg_root, bool disabled = false)
60-
: block_id_(block_id), outmsg_root_(std::move(outmsg_root)), disabled_(disabled) {
65+
Neighbor(ton::BlockIdExt block_id, td::Ref<vm::Cell> outmsg_root, bool disabled = false, td::int32 msg_limit = -1)
66+
: block_id_(block_id), outmsg_root_(std::move(outmsg_root)), disabled_(disabled), msg_limit_(msg_limit) {
6167
}
6268
};
63-
//
64-
ton::ShardIdFull queue_for;
65-
std::vector<std::unique_ptr<MsgKeyValue>> msg_list;
66-
std::vector<Neighbor> neighbors;
6769

68-
public:
69-
OutputQueueMerger(ton::ShardIdFull _queue_for, std::vector<Neighbor> _neighbors);
70-
OutputQueueMerger(ton::ShardIdFull _queue_for, std::vector<block::McShardDescr> _neighbors);
70+
OutputQueueMerger(ton::ShardIdFull queue_for, std::vector<Neighbor> neighbors);
7171
bool is_eof() const {
7272
return eof;
7373
}
@@ -80,10 +80,11 @@ struct OutputQueueMerger {
8080
int common_pfx_len;
8181
std::vector<std::unique_ptr<MsgKeyValue>> heap;
8282
std::size_t pos{0};
83+
std::vector<td::int32> src_remaining_msgs_;
8384
bool eof;
8485
bool failed;
85-
void init();
86-
bool add_root(int src, Ref<vm::Cell> outmsg_root);
86+
bool limit_exceeded{false};
87+
void add_root(int src, Ref<vm::Cell> outmsg_root, td::int32 msg_limit);
8788
bool load();
8889
};
8990

0 commit comments

Comments
 (0)