diff --git a/README.md b/README.md
index df8fefa8..efa5e971 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,26 @@
-# TON
+# TON CatChain
-Main TON monorepo, which includes the code of the node/validator, lite-client, tonlib, FunC compiler, etc.
-
-## Updates flow:
-
-* **master branch** - mainnet is running on this stable branch.
-
- Only emergency updates, urgent updates, or updates that do not affect the main codebase (GitHub workflows / docker images / documentation) are committed directly to this branch.
-
-* **testnet branch** - testnet is running on this branch. The branch contains a set of new updates. After testing, the testnet branch is merged into the master branch and then a new set of updates is added to testnet branch.
-
-* **backlog** - other branches that are candidates to getting into the testnet branch in the next iteration.
-
-Usually, the response to your pull request will indicate which section it falls into.
-
-
-## "Soft" Pull Request rules
-
-* Thou shall not merge your own PRs, at least one person should review the PR and merge it (4-eyes rule)
-* Thou shall make sure that workflows are cleanly completed for your PR before considering merge
-
-## Workflows responsibility
-If a CI workflow fails not because of your changes but workflow issues, try to fix it yourself or contact one of the persons listed below via Telegram messenger:
-
-* **C/C++ CI (ccpp-linux.yml)**: TBD
-* **C/C++ CI Win64 Compile (ccpp-win64.yml)**: TBD
+| Name | Fixed? | Comment |
+|------|---|---------------------------------------|
+|CA2-01| ✔️ | |
+|CA2-02| ✔️ | |
+|CA5-01| ✔️ | `hash(payload)` now also covers block data.
This behavior is enabled by a flag in config. |
+|CA5-02| ✔️ | Size of a block is now limited (16kb).
Block height is now limited, and blocks from misbehaviouring nodes are now ignored.
See `doc/catchain-dos.md` for details. |
+|CA5-03| ✔️ | |
+|CA5-04| ✔️ | |
+|CA5-05| ✔️ | |
+|CA5-06| ✔️ | |
+|CA5-07| ✔️ | |
+|CA5-08| ✔️ | |
+|CA5-09| ✔️ | |
+|CA5-10| ✔️ | |
+|CA5-11| ✔️ | |
+|CAA-01| ✔️ | Fixed in the same way as CA5-01 (hash now covers block data). |
+|CAA-02| ✔️ | |
+|CAE-01| ✔️ | |
+|CAN-01| ✔️ | |
+|CAN-02| ✔️ | |
+|CAT-01| ✔️ | |
+|CAT-02| ✔️ | |
+|CAT-03| ✔️ | |
+|CAT-04| ✔️ | |
diff --git a/catchain/catchain-block.cpp b/catchain/catchain-block.cpp
index f4e76674..e12c89f9 100644
--- a/catchain/catchain-block.cpp
+++ b/catchain/catchain-block.cpp
@@ -22,8 +22,8 @@ namespace ton {
namespace catchain {
-std::unique_ptr CatChainBlock::create(td::uint32 src, td::uint32 fork, PublicKeyHash src_hash,
- CatChainBlockHeight height, CatChainBlockHash hash,
+std::unique_ptr CatChainBlock::create(td::uint32 src, td::uint32 fork, const PublicKeyHash &src_hash,
+ CatChainBlockHeight height, const CatChainBlockHash &hash,
td::SharedSlice payload, CatChainBlock *prev,
std::vector deps,
std::vector vt) {
@@ -31,10 +31,10 @@ std::unique_ptr CatChainBlock::create(td::uint32 src, td::uint32
std::move(deps), std::move(vt));
}
-CatChainBlockImpl::CatChainBlockImpl(td::uint32 src, td::uint32 fork, PublicKeyHash src_hash,
- CatChainBlockHeight height, CatChainBlockHash hash, td::SharedSlice payload,
- CatChainBlock *prev, std::vector deps,
- std::vector vt)
+CatChainBlockImpl::CatChainBlockImpl(td::uint32 src, td::uint32 fork, const PublicKeyHash &src_hash,
+ CatChainBlockHeight height, const CatChainBlockHash &hash,
+ td::SharedSlice payload, CatChainBlock *prev,
+ std::vector deps, std::vector vt)
: src_(src)
, fork_(fork)
, src_hash_(src_hash)
@@ -47,7 +47,7 @@ CatChainBlockImpl::CatChainBlockImpl(td::uint32 src, td::uint32 fork, PublicKeyH
}
bool CatChainBlockImpl::is_descendant_of(CatChainBlock *block) {
- auto fork = block->fork();
+ td::uint32 fork = block->fork();
if (fork >= vt_.size()) {
return false;
}
diff --git a/catchain/catchain-block.hpp b/catchain/catchain-block.hpp
index 8d66d3c1..d37b4dc5 100644
--- a/catchain/catchain-block.hpp
+++ b/catchain/catchain-block.hpp
@@ -103,8 +103,8 @@ class CatChainBlockImpl : public CatChainBlock {
bool is_descendant_of(CatChainBlock *block) override;
- CatChainBlockImpl(td::uint32 src, td::uint32 fork, PublicKeyHash src_hash, CatChainBlockHeight height,
- CatChainBlockHash hash, td::SharedSlice payload, CatChainBlock *prev,
+ CatChainBlockImpl(td::uint32 src, td::uint32 fork, const PublicKeyHash &src_hash, CatChainBlockHeight height,
+ const CatChainBlockHash &hash, td::SharedSlice payload, CatChainBlock *prev,
std::vector deps, std::vector vt);
};
diff --git a/catchain/catchain-received-block.cpp b/catchain/catchain-received-block.cpp
index 7a17d3ee..5996e967 100644
--- a/catchain/catchain-received-block.cpp
+++ b/catchain/catchain-received-block.cpp
@@ -33,7 +33,7 @@ void CatChainReceivedBlockImpl::initialize(tl_object_ptr 0);
+ CHECK(!payload_.empty());
prev_ = dynamic_cast(chain_->create_block(std::move(block->data_->prev_)));
CHECK(prev_ != nullptr);
@@ -51,7 +51,7 @@ void CatChainReceivedBlockImpl::initialize(tl_object_ptris_ill()) {
set_ill();
return;
@@ -63,17 +63,17 @@ void CatChainReceivedBlockImpl::initialize(tl_object_ptrdelivered()) {
pending_deps++;
} else {
- update_deps(prev_);
+ update_vt(prev_);
}
if (!prev_->delivered()) {
prev_->add_rev_dep(this);
}
}
- for (auto &X : block_deps_) {
+ for (CatChainReceivedBlockImpl *X : block_deps_) {
if (!X->delivered()) {
pending_deps++;
} else {
- update_deps(X);
+ update_vt(X);
}
if (!X->delivered()) {
X->add_rev_dep(this);
@@ -121,11 +121,11 @@ void CatChainReceivedBlockImpl::initialize_fork() {
}
}
- if (deps_.size() < fork_id_ + 1) {
- deps_.resize(fork_id_ + 1, 0);
+ if (vt_.size() < fork_id_ + 1) {
+ vt_.resize(fork_id_ + 1, 0);
}
- CHECK(deps_[fork_id_] < height_);
- deps_[fork_id_] = height_;
+ CHECK(vt_[fork_id_] < height_);
+ vt_[fork_id_] = height_;
}
void CatChainReceivedBlockImpl::pre_deliver(ton_api::catchain_block_data_fork &b) {
@@ -153,7 +153,7 @@ void CatChainReceivedBlockImpl::pre_deliver(ton_api::catchain_block_data_fork &b
return;
}
- auto S = chain_->get_source(b.left_->src_);
+ CatChainReceiverSource *S = chain_->get_source(b.left_->src_);
S->on_found_fork_proof(
create_serialize_tl_object(std::move(b.left_), std::move(b.right_)));
S->blame(fork_id_, height_);
@@ -173,15 +173,15 @@ void CatChainReceivedBlockImpl::pre_deliver() {
CHECK(pending_deps_ == 0);
CHECK(in_db_);
- auto M = chain_->get_source(source_id_);
+ CatChainReceiverSource *M = chain_->get_source(source_id_);
- auto d = prev_ ? &prev_->deps_ : nullptr;
+ std::vector *d = prev_ ? &prev_->vt_ : nullptr;
- for (auto &X : block_deps_) {
- auto S = chain_->get_source(X->get_source_id());
- auto &f = S->get_forks();
+ for (CatChainReceivedBlockImpl *X : block_deps_) {
+ CatChainReceiverSource *S = chain_->get_source(X->get_source_id());
+ const std::vector &f = S->get_forks();
if (d) {
- auto &dd = *d;
+ const std::vector &dd = *d;
if (X->get_fork_id() < dd.size() && X->get_height() <= dd[X->get_fork_id()]) {
VLOG(CATCHAIN_WARNING) << this << ": has direct dep from source " << X->get_source_id() << " and prev block "
<< " has newer indirect dep";
@@ -190,8 +190,8 @@ void CatChainReceivedBlockImpl::pre_deliver() {
}
}
if (S->blamed() && d) {
- auto &dd = *d;
- for (auto x : f) {
+ const std::vector &dd = *d;
+ for (td::uint32 x : f) {
if (x != X->get_fork_id() && dd.size() > x && dd[x] > 0) {
VLOG(CATCHAIN_WARNING) << this << ": has direct dep from source " << X->get_source_id() << " and prev block "
<< " has indirect dep to another fork of this source " << x << " " << X->get_fork_id()
@@ -201,7 +201,7 @@ void CatChainReceivedBlockImpl::pre_deliver() {
return;
}
}
- auto v = S->get_blamed_heights();
+ std::vector v = S->get_blamed_heights();
for (size_t i = 0; i < v.size() && i < dd.size(); i++) {
if (v[i] > 0 && dd[i] >= v[i]) {
@@ -220,7 +220,7 @@ void CatChainReceivedBlockImpl::pre_deliver() {
if (X.is_error()) {
is_custom_ = true;
} else {
- ton_api::downcast_call(*X.move_as_ok().get(), [Self = this](auto &obj) { Self->pre_deliver(obj); });
+ ton_api::downcast_call(*X.move_as_ok(), [Self = this](auto &obj) { Self->pre_deliver(obj); });
}
}
@@ -237,7 +237,7 @@ void CatChainReceivedBlockImpl::deliver() {
state_ = bs_delivered;
VLOG(CATCHAIN_DEBUG) << this << ": delivered";
- for (auto &B : rev_deps_) {
+ for (CatChainReceivedBlockImpl *B : rev_deps_) {
B->dep_delivered(this);
}
rev_deps_.clear();
@@ -250,10 +250,10 @@ void CatChainReceivedBlockImpl::set_ill() {
return;
}
VLOG(CATCHAIN_WARNING) << this << ": got ill";
- auto M = chain_->get_source(source_id_);
+ CatChainReceiverSource *M = chain_->get_source(source_id_);
M->blame();
state_ = bs_ill;
- for (auto &B : rev_deps_) {
+ for (CatChainReceivedBlockImpl *B : rev_deps_) {
B->dep_ill(this);
}
}
@@ -262,14 +262,14 @@ void CatChainReceivedBlockImpl::dep_ill(CatChainReceivedBlockImpl *block) {
set_ill();
}
-void CatChainReceivedBlockImpl::update_deps(CatChainReceivedBlockImpl *block) {
- auto &d = block->deps_;
- if (d.size() > deps_.size()) {
- deps_.resize(d.size(), 0);
+void CatChainReceivedBlockImpl::update_vt(CatChainReceivedBlockImpl *block) {
+ const std::vector &d = block->vt_;
+ if (d.size() > vt_.size()) {
+ vt_.resize(d.size(), 0);
}
for (size_t i = 0; i < d.size(); i++) {
- if (deps_[i] < d[i]) {
- deps_[i] = d[i];
+ if (vt_[i] < d[i]) {
+ vt_[i] = d[i];
}
}
}
@@ -279,7 +279,7 @@ void CatChainReceivedBlockImpl::dep_delivered(CatChainReceivedBlockImpl *block)
return;
}
CHECK(!block->is_ill());
- update_deps(block);
+ update_vt(block);
pending_deps_--;
if (pending_deps_ == 0 && in_db_) {
schedule();
@@ -332,35 +332,37 @@ void CatChainReceivedBlockImpl::find_pending_deps(std::vector
if (prev_) {
prev_->find_pending_deps(vec, max_size);
}
- for (auto &X : block_deps_) {
+ for (CatChainReceivedBlockImpl *X : block_deps_) {
X->find_pending_deps(vec, max_size);
}
}
-tl_object_ptr CatChainReceivedBlock::block_id(CatChainReceiver *chain,
- tl_object_ptr &block,
- td::Slice payload) {
+tl_object_ptr CatChainReceivedBlock::block_id(
+ const CatChainReceiver *chain, const tl_object_ptr &block, const td::Slice &payload) {
+ td::Bits256 hash = data_payload_hash(chain, block->data_, payload);
return create_tl_object(block->incarnation_, chain->get_source_hash(block->src_).tl(),
- block->height_, sha256_bits256(payload));
+ block->height_, hash);
}
tl_object_ptr CatChainReceivedBlock::block_id(
- CatChainReceiver *chain, tl_object_ptr &block) {
+ const CatChainReceiver *chain, const tl_object_ptr &block) {
return create_tl_object(
chain->get_incarnation(), chain->get_source_hash(block->src_).tl(), block->height_, block->data_hash_);
}
-CatChainBlockHash CatChainReceivedBlock::block_hash(CatChainReceiver *chain,
- tl_object_ptr &block, td::Slice payload) {
+CatChainBlockHash CatChainReceivedBlock::block_hash(const CatChainReceiver *chain,
+ const tl_object_ptr &block,
+ const td::Slice &payload) {
return get_tl_object_sha_bits256(block_id(chain, block, payload));
}
-CatChainBlockHash CatChainReceivedBlock::block_hash(CatChainReceiver *chain,
- tl_object_ptr &block) {
+CatChainBlockHash CatChainReceivedBlock::block_hash(const CatChainReceiver *chain,
+ const tl_object_ptr &block) {
return get_tl_object_sha_bits256(block_id(chain, block));
}
-td::Status CatChainReceivedBlock::pre_validate_block(CatChainReceiver *chain,
- tl_object_ptr &block, td::Slice payload) {
+td::Status CatChainReceivedBlock::pre_validate_block(const CatChainReceiver *chain,
+ const tl_object_ptr &block,
+ const td::Slice &payload) {
CHECK(block->incarnation_ == chain->get_incarnation());
if (block->height_ <= 0) {
return td::Status::Error(ErrorCode::protoviolation, std::string("bad height ") + std::to_string(block->height_));
@@ -397,7 +399,7 @@ td::Status CatChainReceivedBlock::pre_validate_block(CatChainReceiver *chain,
std::set used;
used.insert(block->src_);
- for (auto &X : block->data_->deps_) {
+ for (const auto &X : block->data_->deps_) {
if (used.find(X->src_) != used.end()) {
return td::Status::Error(ErrorCode::protoviolation, "two deps from same source");
}
@@ -405,19 +407,19 @@ td::Status CatChainReceivedBlock::pre_validate_block(CatChainReceiver *chain,
}
TRY_STATUS(chain->validate_block_sync(block->data_->prev_));
- for (auto &X : block->data_->deps_) {
+ for (const auto &X : block->data_->deps_) {
TRY_STATUS(chain->validate_block_sync(X));
}
- if (payload.size() == 0) {
+ if (payload.empty()) {
return td::Status::Error(ErrorCode::protoviolation, "empty payload");
}
return td::Status::OK();
}
-td::Status CatChainReceivedBlock::pre_validate_block(CatChainReceiver *chain,
- tl_object_ptr &block) {
+td::Status CatChainReceivedBlock::pre_validate_block(const CatChainReceiver *chain,
+ const tl_object_ptr &block) {
if (block->height_ < 0) {
return td::Status::Error(ErrorCode::protoviolation, std::string("bad height ") + std::to_string(block->height_));
}
@@ -430,7 +432,7 @@ td::Status CatChainReceivedBlock::pre_validate_block(CatChainReceiver *chain,
return td::Status::Error(ErrorCode::protoviolation,
std::string("bad src (first block) ") + std::to_string(block->src_));
}
- if (block->data_hash_ != chain->get_incarnation() || block->signature_.size() != 0) {
+ if (block->data_hash_ != chain->get_incarnation() || !block->signature_.empty()) {
return td::Status::Error(ErrorCode::protoviolation, std::string("bad first block"));
}
}
@@ -443,9 +445,10 @@ tl_object_ptr CatChainReceivedBlockImpl::export_tl() co
CHECK(height_ > 0);
std::vector> deps;
- for (auto &B : block_deps_) {
+ for (CatChainReceivedBlockImpl *B : block_deps_) {
deps.push_back(B->export_tl_dep());
}
+ CHECK(deps.size() <= chain_->opts().max_deps)
return create_tl_object(
chain_->get_incarnation(), source_id_, height_,
@@ -454,35 +457,34 @@ tl_object_ptr CatChainReceivedBlockImpl::export_tl() co
}
tl_object_ptr CatChainReceivedBlockImpl::export_tl_dep() const {
- return create_tl_object(source_id_, height_, data_hash_,
+ return create_tl_object(source_id_, height_, data_payload_hash_,
signature_.clone_as_buffer_slice());
}
-CatChainReceivedBlockImpl::CatChainReceivedBlockImpl(td::uint32 source_id, CatChainSessionId hash,
+CatChainReceivedBlockImpl::CatChainReceivedBlockImpl(td::uint32 source_id, const CatChainBlockPayloadHash &hash,
CatChainReceiver *chain) {
chain_ = chain;
state_ = bs_delivered;
fork_id_ = 0;
source_id_ = source_id;
- data_ = nullptr;
- prev_ = nullptr;
height_ = 0;
- data_hash_ = hash;
- hash_ = get_tl_object_sha_bits256(create_tl_object(
- chain->get_incarnation(), chain->get_incarnation(), height_, data_hash_));
+ data_payload_hash_ = hash;
+ block_id_hash_ = get_tl_object_sha_bits256(create_tl_object(
+ chain->get_incarnation(), chain->get_incarnation(), height_, data_payload_hash_));
}
CatChainReceivedBlockImpl::CatChainReceivedBlockImpl(tl_object_ptr block,
td::SharedSlice payload, CatChainReceiver *chain) {
chain_ = chain;
- data_hash_ = sha256_bits256(payload.as_slice());
- hash_ = get_tl_object_sha_bits256(create_tl_object(
- block->incarnation_, chain->get_source_hash(block->src_).tl(), block->height_, data_hash_));
+ data_payload_hash_ = data_payload_hash(chain, block->data_, payload);
+ block_id_hash_ = get_tl_object_sha_bits256(create_tl_object(
+ block->incarnation_, chain->get_source_hash(block->src_).tl(), block->height_, data_payload_hash_));
height_ = block->height_;
source_id_ = block->src_;
+ CHECK(height_ <= get_max_block_height(chain->opts(), chain->get_sources_cnt()));
- auto S = chain_->get_source(source_id_);
+ CatChainReceiverSource *S = chain_->get_source(source_id_);
S->on_new_block(this);
initialize(std::move(block), std::move(payload));
@@ -491,14 +493,14 @@ CatChainReceivedBlockImpl::CatChainReceivedBlockImpl(tl_object_ptr block,
CatChainReceiver *chain) {
chain_ = chain;
- data_hash_ = block->data_hash_;
+ data_payload_hash_ = block->data_hash_;
source_id_ = block->src_;
signature_ = td::SharedSlice{block->signature_.as_slice()};
- hash_ = get_tl_object_sha_bits256(create_tl_object(
- chain_->get_incarnation(), chain_->get_source_hash(source_id_).tl(), block->height_, data_hash_));
+ block_id_hash_ = get_tl_object_sha_bits256(create_tl_object(
+ chain_->get_incarnation(), chain_->get_source_hash(source_id_).tl(), block->height_, data_payload_hash_));
height_ = block->height_;
- auto S = chain_->get_source(source_id_);
+ CatChainReceiverSource *S = chain_->get_source(source_id_);
S->on_new_block(this);
}
@@ -513,9 +515,24 @@ std::unique_ptr CatChainReceivedBlock::create(tl_object_p
}
std::unique_ptr CatChainReceivedBlock::create_root(td::uint32 source_id,
- CatChainSessionId data_hash,
+ CatChainSessionId session_id,
CatChainReceiver *chain) {
- return std::make_unique(source_id, data_hash, chain);
+ return std::make_unique(source_id, session_id, chain);
+}
+
+CatChainBlockPayloadHash CatChainReceivedBlock::data_payload_hash(
+ const CatChainReceiver *chain, const tl_object_ptr &data, const td::Slice &payload) {
+ td::Bits256 hash = sha256_bits256(payload);
+ if (chain->opts().block_hash_covers_data) {
+ td::Bits256 data_hash = get_tl_object_sha_bits256(data);
+ char buf[32 * 2];
+ CHECK(hash.as_array().size() == 32 && data_hash.as_array().size() == 32);
+ std::copy(hash.as_array().begin(), hash.as_array().end(), buf);
+ std::copy(data_hash.as_array().begin(), data_hash.as_array().end(), buf + 32);
+ return sha256_bits256(td::Slice(buf, buf + 64));
+ } else {
+ return hash;
+ }
}
} // namespace catchain
diff --git a/catchain/catchain-received-block.h b/catchain/catchain-received-block.h
index 8a5dfa90..3c4f5d76 100644
--- a/catchain/catchain-received-block.h
+++ b/catchain/catchain-received-block.h
@@ -30,7 +30,6 @@ namespace catchain {
class CatChainReceiver;
class CatChainReceiverSource;
-class CatChainReceiverFork;
class CatChainReceivedBlock {
public:
@@ -43,7 +42,7 @@ class CatChainReceivedBlock {
virtual CatChainReceivedBlock *get_prev() const = 0;
virtual CatChainBlockHash get_prev_hash() const = 0;
- virtual const std::vector &get_deps() const = 0;
+ virtual const std::vector &get_vt() const = 0;
virtual std::vector get_dep_hashes() const = 0;
virtual CatChainReceiver *get_chain() const = 0;
@@ -56,6 +55,8 @@ class CatChainReceivedBlock {
virtual void find_pending_deps(std::vector &vec, td::uint32 max_size) const = 0;
+ virtual bool has_rev_deps() const = 0;
+
public:
// state
virtual bool initialized() const = 0;
@@ -76,20 +77,28 @@ class CatChainReceivedBlock {
td::SharedSlice payload, CatChainReceiver *chain);
static std::unique_ptr create(tl_object_ptr block,
CatChainReceiver *chain);
- static std::unique_ptr create_root(td::uint32 source_id, CatChainBlockPayloadHash data_hash,
+ static std::unique_ptr create_root(td::uint32 source_id, CatChainSessionId session_id,
CatChainReceiver *chain);
- static tl_object_ptr block_id(CatChainReceiver *chain,
- tl_object_ptr &block,
- td::Slice payload);
- static tl_object_ptr block_id(CatChainReceiver *chain,
- tl_object_ptr &block);
- static CatChainBlockHash block_hash(CatChainReceiver *chain, tl_object_ptr &block,
- td::Slice payload);
- static CatChainBlockHash block_hash(CatChainReceiver *chain, tl_object_ptr &block);
- static td::Status pre_validate_block(CatChainReceiver *chain, tl_object_ptr &block,
- td::Slice payload);
- static td::Status pre_validate_block(CatChainReceiver *chain, tl_object_ptr &block);
+ static tl_object_ptr block_id(const CatChainReceiver *chain,
+ const tl_object_ptr &block,
+ const td::Slice &payload);
+ static tl_object_ptr block_id(const CatChainReceiver *chain,
+ const tl_object_ptr &block);
+ static CatChainBlockHash block_hash(const CatChainReceiver *chain,
+ const tl_object_ptr &block,
+ const td::Slice &payload);
+ static CatChainBlockHash block_hash(const CatChainReceiver *chain,
+ const tl_object_ptr &block);
+ static td::Status pre_validate_block(const CatChainReceiver *chain,
+ const tl_object_ptr &block,
+ const td::Slice &payload);
+ static td::Status pre_validate_block(const CatChainReceiver *chain,
+ const tl_object_ptr &block);
+ static CatChainBlockPayloadHash data_payload_hash(const CatChainReceiver *chain,
+ const tl_object_ptr &data,
+ const td::Slice &payload);
+
virtual ~CatChainReceivedBlock() = default;
};
diff --git a/catchain/catchain-received-block.hpp b/catchain/catchain-received-block.hpp
index 27f9ec61..f1270ab0 100644
--- a/catchain/catchain-received-block.hpp
+++ b/catchain/catchain-received-block.hpp
@@ -26,15 +26,14 @@ namespace catchain {
class CatChainReceiver;
class CatChainReceiverSource;
-class CatChainReceiverFork;
-class CatChainReceivedBlockImpl : public CatChainReceivedBlock {
+class CatChainReceivedBlockImpl final : public CatChainReceivedBlock {
public:
const td::SharedSlice &get_payload() const override {
return payload_;
}
CatChainBlockHash get_hash() const override {
- return hash_;
+ return block_id_hash_;
}
const td::SharedSlice &get_signature() const override {
return signature_;
@@ -46,8 +45,8 @@ class CatChainReceivedBlockImpl : public CatChainReceivedBlock {
CatChainReceivedBlock *get_prev() const override;
CatChainBlockHash get_prev_hash() const override;
- const std::vector &get_deps() const override {
- return deps_;
+ const std::vector &get_vt() const override {
+ return vt_;
}
std::vector get_dep_hashes() const override;
@@ -69,6 +68,10 @@ class CatChainReceivedBlockImpl : public CatChainReceivedBlock {
void find_pending_deps(std::vector &vec, td::uint32 max_size) const override;
+ bool has_rev_deps() const override {
+ return !rev_deps_.empty();
+ }
+
public:
bool initialized() const override {
return state_ >= bs_initialized;
@@ -114,7 +117,7 @@ class CatChainReceivedBlockImpl : public CatChainReceivedBlock {
CatChainReceiver *chain);
CatChainReceivedBlockImpl(tl_object_ptr block, CatChainReceiver *chain);
- CatChainReceivedBlockImpl(td::uint32 source_id, CatChainSessionId hash, CatChainReceiver *chain);
+ CatChainReceivedBlockImpl(td::uint32 source_id, const CatChainSessionId &hash, CatChainReceiver *chain);
private:
enum State {
@@ -124,31 +127,28 @@ class CatChainReceivedBlockImpl : public CatChainReceivedBlock {
bs_delivered,
} state_ = bs_none;
- void update_deps(CatChainReceivedBlockImpl *block);
+ void update_vt(CatChainReceivedBlockImpl *block);
void add_rev_dep(CatChainReceivedBlockImpl *block);
- void add_child_dep(CatChainReceivedBlockImpl *block);
void initialize_fork();
- void on_ready_to_deliver();
td::uint32 fork_id_{0};
td::uint32 source_id_;
CatChainReceiver *chain_;
- tl_object_ptr data_;
td::SharedSlice payload_;
- CatChainBlockHash hash_;
- CatChainBlockPayloadHash data_hash_;
+ CatChainBlockHash block_id_hash_{};
+ CatChainBlockPayloadHash data_payload_hash_{};
- CatChainReceivedBlockImpl *prev_;
+ CatChainReceivedBlockImpl *prev_ = nullptr;
CatChainBlockHeight height_;
CatChainReceivedBlockImpl *next_ = nullptr;
std::vector block_deps_;
- std::vector deps_;
+ std::vector vt_;
td::SharedSlice signature_;
diff --git a/catchain/catchain-receiver-interface.h b/catchain/catchain-receiver-interface.h
index af983402..c8f1ef66 100644
--- a/catchain/catchain-receiver-interface.h
+++ b/catchain/catchain-receiver-interface.h
@@ -35,33 +35,33 @@ class CatChainReceiverInterface : public td::actor::Actor {
CatChainBlockHash prev, std::vector deps,
std::vector vt, td::SharedSlice data) = 0;
virtual void blame(td::uint32 src_id) = 0;
- virtual void on_custom_message(PublicKeyHash src, td::BufferSlice data) = 0;
- virtual void on_custom_query(PublicKeyHash src, td::BufferSlice data, td::Promise promise) = 0;
- virtual void on_broadcast(PublicKeyHash src, td::BufferSlice data) = 0;
+ virtual void on_custom_query(const PublicKeyHash &src, td::BufferSlice data,
+ td::Promise promise) = 0;
+ virtual void on_broadcast(const PublicKeyHash &src, td::BufferSlice data) = 0;
virtual void start() = 0;
virtual ~Callback() = default;
};
virtual void add_block(td::BufferSlice payload, std::vector deps) = 0;
virtual void debug_add_fork(td::BufferSlice payload, CatChainBlockHeight height,
std::vector deps) = 0;
- virtual void blame_node(td::uint32 idx) = 0;
virtual void send_fec_broadcast(td::BufferSlice data) = 0;
- virtual void send_custom_query_data(PublicKeyHash dst, std::string name, td::Promise promise,
+ virtual void send_custom_query_data(const PublicKeyHash &dst, std::string name, td::Promise promise,
td::Timestamp timeout, td::BufferSlice query) = 0;
- virtual void send_custom_query_data_via(PublicKeyHash dst, std::string name, td::Promise promise,
- td::Timestamp timeout, td::BufferSlice query, td::uint64 max_answer_size,
+ virtual void send_custom_query_data_via(const PublicKeyHash &dst, std::string name,
+ td::Promise promise, td::Timestamp timeout,
+ td::BufferSlice query, td::uint64 max_answer_size,
td::actor::ActorId via) = 0;
- virtual void send_custom_message_data(PublicKeyHash dst, td::BufferSlice query) = 0;
+ virtual void send_custom_message_data(const PublicKeyHash &dst, td::BufferSlice query) = 0;
virtual void destroy() = 0;
static td::actor::ActorOwn create(
- std::unique_ptr callback, CatChainOptions opts, td::actor::ActorId keyring,
+ std::unique_ptr callback, const CatChainOptions &opts, td::actor::ActorId keyring,
td::actor::ActorId adnl, td::actor::ActorId overlay_manager,
- std::vector ids, PublicKeyHash local_id, CatChainSessionId unique_hash, std::string db_root,
- std::string db_suffix, bool allow_unsafe_self_blocks_resync);
+ const std::vector &ids, const PublicKeyHash &local_id, const CatChainSessionId &unique_hash,
+ std::string db_root, std::string db_suffix, bool allow_unsafe_self_blocks_resync);
- virtual ~CatChainReceiverInterface() = default;
+ ~CatChainReceiverInterface() override = default;
};
} // namespace catchain
diff --git a/catchain/catchain-receiver-source.cpp b/catchain/catchain-receiver-source.cpp
index aca522dc..6a9e0777 100644
--- a/catchain/catchain-receiver-source.cpp
+++ b/catchain/catchain-receiver-source.cpp
@@ -24,10 +24,10 @@ namespace ton {
namespace catchain {
td::uint32 CatChainReceiverSourceImpl::add_fork() {
- if (fork_ids_.size() > 0) {
+ if (!fork_ids_.empty()) {
blame();
}
- auto F = chain_->add_fork();
+ td::uint32 F = chain_->add_fork();
CHECK(F > 0);
fork_ids_.push_back(F);
@@ -60,7 +60,7 @@ td::Result> CatChainReceiverSource::crea
void CatChainReceiverSourceImpl::blame(td::uint32 fork, CatChainBlockHeight height) {
blame();
- if (blamed_heights_.size() > 0) {
+ if (!blamed_heights_.empty()) {
if (blamed_heights_.size() <= fork) {
blamed_heights_.resize(fork + 1, 0);
}
@@ -130,19 +130,6 @@ void CatChainReceiverSourceImpl::block_delivered(CatChainBlockHeight height) {
}
}
-td::Status CatChainReceiverSourceImpl::validate_dep_sync(tl_object_ptr &dep) {
- auto S = std::move(dep->signature_);
- auto str = serialize_tl_object(dep, true);
- dep->signature_ = std::move(S);
-
- auto R = encryptor_sync_->check_signature(str.as_slice(), dep->signature_.as_slice());
- if (R.is_error()) {
- return R.move_as_error();
- }
-
- return td::Status::OK();
-}
-
void CatChainReceiverSourceImpl::on_new_block(CatChainReceivedBlock *block) {
if (fork_is_found()) {
return;
@@ -165,7 +152,7 @@ void CatChainReceiverSourceImpl::on_new_block(CatChainReceivedBlock *block) {
blocks_[block->get_height()] = block;
}
-void CatChainReceiverSourceImpl::on_found_fork_proof(td::Slice proof) {
+void CatChainReceiverSourceImpl::on_found_fork_proof(const td::Slice &proof) {
if (!fork_is_found()) {
fetch_tl_object(proof, true).ensure();
fork_proof_ = td::SharedSlice{proof};
diff --git a/catchain/catchain-receiver-source.h b/catchain/catchain-receiver-source.h
index 11faf3db..e805c2a5 100644
--- a/catchain/catchain-receiver-source.h
+++ b/catchain/catchain-receiver-source.h
@@ -56,9 +56,8 @@ class CatChainReceiverSource {
virtual bool has_unreceived() const = 0;
virtual bool has_undelivered() const = 0;
- virtual td::Status validate_dep_sync(tl_object_ptr &dep) = 0;
virtual void on_new_block(CatChainReceivedBlock *block) = 0;
- virtual void on_found_fork_proof(td::Slice fork) = 0;
+ virtual void on_found_fork_proof(const td::Slice &fork) = 0;
virtual td::BufferSlice fork_proof() const = 0;
virtual bool fork_is_found() const = 0;
diff --git a/catchain/catchain-receiver-source.hpp b/catchain/catchain-receiver-source.hpp
index 74082b45..0785d8c2 100644
--- a/catchain/catchain-receiver-source.hpp
+++ b/catchain/catchain-receiver-source.hpp
@@ -23,6 +23,7 @@
#include "catchain-receiver-source.h"
#include "catchain-receiver.h"
#include "catchain-received-block.h"
+#include
namespace ton {
@@ -82,7 +83,7 @@ class CatChainReceiverSourceImpl : public CatChainReceiverSource {
if (blamed()) {
return true;
}
- if (!blocks_.size()) {
+ if (blocks_.empty()) {
return false;
}
CHECK(blocks_.rbegin()->second->get_height() >= received_height_);
@@ -93,9 +94,8 @@ class CatChainReceiverSourceImpl : public CatChainReceiverSource {
}
CatChainReceivedBlock *get_block(CatChainBlockHeight height) const override;
- td::Status validate_dep_sync(tl_object_ptr &dep) override;
void on_new_block(CatChainReceivedBlock *block) override;
- void on_found_fork_proof(td::Slice proof) override;
+ void on_found_fork_proof(const td::Slice &proof) override;
bool fork_is_found() const override {
return !fork_proof_.empty();
}
@@ -103,7 +103,7 @@ class CatChainReceiverSourceImpl : public CatChainReceiverSource {
if (!fork_proof_.empty()) {
return fork_proof_.clone_as_buffer_slice();
} else {
- return td::BufferSlice();
+ return {};
}
}
diff --git a/catchain/catchain-receiver.cpp b/catchain/catchain-receiver.cpp
index e7f5c019..488fbb9d 100644
--- a/catchain/catchain-receiver.cpp
+++ b/catchain/catchain-receiver.cpp
@@ -17,6 +17,7 @@
Copyright 2017-2020 Telegram Systems LLP
*/
#include
+#include
#include "td/actor/PromiseFuture.h"
#include "td/utils/Random.h"
#include "td/db/RocksDb.h"
@@ -30,6 +31,25 @@ namespace ton {
namespace catchain {
+static const td::uint32 MAX_NEIGHBOURS = 5;
+static const double EXPECTED_UNSAFE_INITIAL_SYNC_DURATION = 300.0;
+static const double EXPECTED_INITIAL_SYNC_DURATION = 5.0;
+static const td::uint32 OVERLAY_MAX_ALLOWED_PACKET_SIZE = 16 * 1024 * 1024;
+static const double NEIGHBOURS_ROTATE_INTERVAL_MIN = 60;
+static const double NEIGHBOURS_ROTATE_INTERVAL_MAX = 120;
+static const td::uint32 MAX_QUERY_BLOCKS = 100;
+static const td::uint32 MAX_QUERY_HEIGHT = 100;
+static const td::uint32 GET_DIFFERENCE_MAX_SEND = 100;
+static const double GET_DIFFERENCE_TIMEOUT = 5.0;
+static const double GET_BLOCK_TIMEOUT = 2.0;
+static const td::uint32 MAX_PENDING_DEPS = 16;
+static const double EXPECTED_INITIAL_SYNC_DURATION_WITH_UNPROCESSED = 60.0;
+static const double SYNC_INTERVAL_MIN = 0.1;
+static const double SYNC_INTERVAL_MAX = 0.2;
+static const td::uint32 SYNC_ITERATIONS = 3;
+static const double DESTROY_DB_DELAY = 1.0;
+static const td::uint32 DESTROY_DB_MAX_ATTEMPTS = 10;
+
PublicKeyHash CatChainReceiverImpl::get_source_hash(td::uint32 source_id) const {
CHECK(source_id < sources_.size());
return sources_[source_id]->get_hash();
@@ -45,18 +65,19 @@ void CatChainReceiverImpl::deliver_block(CatChainReceivedBlock *block) {
<< " custom=" << block->is_custom();
callback_->new_block(block->get_source_id(), block->get_fork_id(), block->get_hash(), block->get_height(),
block->get_height() == 1 ? CatChainBlockHash::zero() : block->get_prev_hash(),
- block->get_dep_hashes(), block->get_deps(),
+ block->get_dep_hashes(), block->get_vt(),
block->is_custom() ? block->get_payload().clone() : td::SharedSlice());
std::vector v;
- for (auto it : neighbours_) {
- auto S = get_source(it);
+ for (td::uint32 it : neighbours_) {
+ CatChainReceiverSource *S = get_source(it);
v.push_back(S->get_adnl_id());
}
auto update = create_tl_object(block->export_tl());
- auto D = serialize_tl_object(update, true, block->get_payload().as_slice());
+ td::BufferSlice D = serialize_tl_object(update, true, block->get_payload().as_slice());
+ CHECK(D.size() <= opts_.max_serialized_block_size);
td::actor::send_closure(overlay_manager_, &overlay::Overlays::send_multiple_messages, std::move(v),
get_source(local_idx_)->get_adnl_id(), overlay_id_, std::move(D));
@@ -64,8 +85,8 @@ void CatChainReceiverImpl::deliver_block(CatChainReceivedBlock *block) {
void CatChainReceiverImpl::receive_block(adnl::AdnlNodeIdShort src, tl_object_ptr block,
td::BufferSlice payload) {
- auto id = CatChainReceivedBlock::block_hash(this, block, payload);
- auto B = get_block(id);
+ CatChainBlockHash id = CatChainReceivedBlock::block_hash(this, block, payload);
+ CatChainReceivedBlock *B = get_block(id);
if (B && B->initialized()) {
return;
}
@@ -76,7 +97,27 @@ void CatChainReceiverImpl::receive_block(adnl::AdnlNodeIdShort src, tl_object_pt
return;
}
- auto S = validate_block_sync(block, payload.as_slice());
+ td::uint64 max_block_height = get_max_block_height(opts_, sources_.size());
+ if ((td::uint32)block->height_ > max_block_height) {
+ VLOG(CATCHAIN_WARNING) << this << ": received too many blocks from " << src
+ << " (limit=" << max_block_height << ")";
+ return;
+ }
+
+ td::uint32 src_id = block->src_;
+ if (src_id >= get_sources_cnt()) {
+ VLOG(CATCHAIN_WARNING) << this << ": received broken block from " << src << ": bad src " << block->src_;
+ return;
+ }
+ CatChainReceiverSource *source = get_source(src_id);
+ if (source->fork_is_found()) {
+ if (B == nullptr || !B->has_rev_deps()) {
+ VLOG(CATCHAIN_WARNING) << this << ": dropping block from source " << src_id << ": source has a fork";
+ return;
+ }
+ }
+
+ td::Status S = validate_block_sync(block, payload.as_slice());
if (S.is_error()) {
VLOG(CATCHAIN_WARNING) << this << ": received broken block from " << src << ": " << S.move_as_error();
@@ -89,11 +130,11 @@ void CatChainReceiverImpl::receive_block(adnl::AdnlNodeIdShort src, tl_object_pt
<< " (unsafe=" << allow_unsafe_self_blocks_resync_ << ")";
} else {
LOG(ERROR) << this << ": received unknown SELF block from " << src << ". UPDATING LOCAL DATABASE. UNSAFE";
- initial_sync_complete_at_ = td::Timestamp::in(300.0);
+ initial_sync_complete_at_ = td::Timestamp::in(EXPECTED_UNSAFE_INITIAL_SYNC_DURATION);
}
}
- auto raw_data = serialize_tl_object(block, true, payload.as_slice());
+ td::BufferSlice raw_data = serialize_tl_object(block, true, payload.as_slice());
create_block(std::move(block), td::SharedSlice{payload.as_slice()});
if (!opts_.debug_disable_db) {
@@ -104,6 +145,11 @@ void CatChainReceiverImpl::receive_block(adnl::AdnlNodeIdShort src, tl_object_pt
}
void CatChainReceiverImpl::receive_block_answer(adnl::AdnlNodeIdShort src, td::BufferSlice data) {
+ if (data.size() > opts_.max_serialized_block_size) {
+ VLOG(CATCHAIN_INFO) << this << ": received bad block result " << src << ": too big (size="
+ << data.size() << ", limit=" << opts_.max_serialized_block_size << ")";
+ return;
+ }
auto F = fetch_tl_prefix(data, true);
if (F.is_error()) {
VLOG(CATCHAIN_INFO) << this << ": received bad block result: " << F.move_as_error();
@@ -111,7 +157,7 @@ void CatChainReceiverImpl::receive_block_answer(adnl::AdnlNodeIdShort src, td::B
}
auto f = F.move_as_ok();
ton_api::downcast_call(
- *f.get(),
+ *f,
td::overloaded(
[&](ton_api::catchain_blockNotFound &r) { VLOG(CATCHAIN_INFO) << this << ": catchain block not found"; },
[&](ton_api::catchain_blockResult &r) { receive_block(src, std::move(r.block_), std::move(data)); }));
@@ -129,6 +175,11 @@ void CatChainReceiverImpl::receive_message_from_overlay(adnl::AdnlNodeIdShort sr
VLOG(CATCHAIN_INFO) << this << ": dropping block update from blamed source " << src;
return;
}*/
+ if (data.size() > opts_.max_serialized_block_size) {
+ VLOG(CATCHAIN_WARNING) << this << ": dropping broken block from " << src << ": too big (size="
+ << data.size() << ", limit=" << opts_.max_serialized_block_size << ")";
+ return;
+ }
auto R = fetch_tl_prefix(data, true);
if (R.is_error()) {
VLOG(CATCHAIN_WARNING) << this << ": dropping broken block from " << src << ": " << R.move_as_error();
@@ -139,14 +190,14 @@ void CatChainReceiverImpl::receive_message_from_overlay(adnl::AdnlNodeIdShort sr
receive_block(src, std::move(U->block_), std::move(data));
}
-void CatChainReceiverImpl::receive_broadcast_from_overlay(PublicKeyHash src, td::BufferSlice data) {
+void CatChainReceiverImpl::receive_broadcast_from_overlay(const PublicKeyHash &src, td::BufferSlice data) {
if (!read_db_) {
return;
}
callback_->on_broadcast(src, std::move(data));
}
-/*void CatChainReceiverImpl::send_block(PublicKeyHash src, tl_object_ptr block,
+/*void CatChainReceiverImpl::send_block(const PublicKeyHash &src, tl_object_ptr block,
td::BufferSlice payload) {
CHECK(read_db_);
CHECK(src == local_id_);
@@ -164,7 +215,7 @@ CatChainReceivedBlock *CatChainReceiverImpl::create_block(tl_object_ptrheight_ == 0) {
return root_block_;
}
- auto hash = CatChainReceivedBlock::block_hash(this, block, payload.as_slice());
+ CatChainBlockHash hash = CatChainReceivedBlock::block_hash(this, block, payload.as_slice());
auto it = blocks_.find(hash);
if (it != blocks_.end()) {
@@ -173,9 +224,8 @@ CatChainReceivedBlock *CatChainReceiverImpl::create_block(tl_object_ptrsecond.get();
} else {
- blocks_.emplace(hash, CatChainReceivedBlock::create(std::move(block), std::move(payload), this));
- it = blocks_.find(hash);
- return it->second.get();
+ auto r = blocks_.emplace(hash, CatChainReceivedBlock::create(std::move(block), std::move(payload), this));
+ return r.first->second.get();
}
}
@@ -183,7 +233,7 @@ CatChainReceivedBlock *CatChainReceiverImpl::create_block(tl_object_ptrheight_ == 0) {
return root_block_;
}
- auto hash = CatChainReceivedBlock::block_hash(this, block);
+ CatChainBlockHash hash = CatChainReceivedBlock::block_hash(this, block);
auto it = blocks_.find(hash);
if (it != blocks_.end()) {
return it->second.get();
@@ -194,20 +244,20 @@ CatChainReceivedBlock *CatChainReceiverImpl::create_block(tl_object_ptr &dep) {
+td::Status CatChainReceiverImpl::validate_block_sync(const tl_object_ptr &dep) const {
TRY_STATUS_PREFIX(CatChainReceivedBlock::pre_validate_block(this, dep), "failed to validate block: ");
if (dep->height_ > 0) {
auto id = CatChainReceivedBlock::block_id(this, dep);
- auto B = serialize_tl_object(id, true);
- auto block = get_block(get_tl_object_sha_bits256(id));
+ td::BufferSlice B = serialize_tl_object(id, true);
+ CatChainReceivedBlock *block = get_block(get_tl_object_sha_bits256(id));
if (block) {
return td::Status::OK();
}
- auto S = get_source_by_hash(PublicKeyHash{id->src_});
+ CatChainReceiverSource *S = get_source_by_hash(PublicKeyHash{id->src_});
CHECK(S != nullptr);
- auto E = S->get_encryptor_sync();
+ Encryptor *E = S->get_encryptor_sync();
CHECK(E != nullptr);
return E->check_signature(B.as_slice(), dep->signature_.as_slice());
} else {
@@ -215,17 +265,18 @@ td::Status CatChainReceiverImpl::validate_block_sync(tl_object_ptr &block, td::Slice payload) {
+td::Status CatChainReceiverImpl::validate_block_sync(const tl_object_ptr &block,
+ const td::Slice &payload) const {
//LOG(INFO) << ton_api::to_string(block);
TRY_STATUS_PREFIX(CatChainReceivedBlock::pre_validate_block(this, block, payload), "failed to validate block: ");
if (block->height_ > 0) {
auto id = CatChainReceivedBlock::block_id(this, block, payload);
- auto B = serialize_tl_object(id, true);
+ td::BufferSlice B = serialize_tl_object(id, true);
- auto S = get_source_by_hash(PublicKeyHash{id->src_});
+ CatChainReceiverSource *S = get_source_by_hash(PublicKeyHash{id->src_});
CHECK(S != nullptr);
- auto E = S->get_encryptor_sync();
+ Encryptor *E = S->get_encryptor_sync();
CHECK(E != nullptr);
return E->check_signature(B.as_slice(), block->signature_.as_slice());
} else {
@@ -235,7 +286,7 @@ td::Status CatChainReceiverImpl::validate_block_sync(tl_object_ptrrun();
@@ -265,7 +316,7 @@ void CatChainReceiverImpl::add_block_cont_3(tl_object_ptr 0) {
+ if (!pending_blocks_.empty()) {
auto B = std::move(pending_blocks_.front());
pending_blocks_.pop_front();
add_block(std::move(B->payload_), std::move(B->deps_));
@@ -278,9 +329,9 @@ void CatChainReceiverImpl::add_block_cont_2(tl_object_ptr
add_block_cont_2(std::move(block), std::move(payload));
return;
}
- auto id = CatChainReceivedBlock::block_hash(this, block, payload.as_slice());
+ CatChainBlockHash id = CatChainReceivedBlock::block_hash(this, block, payload.as_slice());
- auto raw_data = serialize_tl_object(block, true, payload.as_slice());
+ td::BufferSlice raw_data = serialize_tl_object(block, true, payload.as_slice());
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), block = std::move(block),
payload = std::move(payload)](td::Result R) mutable {
@@ -319,7 +370,7 @@ void CatChainReceiverImpl::add_block(td::BufferSlice payload, std::vectorget_id() == local_idx_);
if (!intentional_fork_) {
@@ -331,7 +382,7 @@ void CatChainReceiverImpl::add_block(td::BufferSlice payload, std::vector> deps_arr;
deps_arr.resize(deps.size());
for (size_t i = 0; i < deps.size(); i++) {
- auto B = get_block(deps[i]);
+ CatChainReceivedBlock *B = get_block(deps[i]);
LOG_CHECK(B != nullptr) << this << ": cannot find block with hash " << deps[i];
if (!intentional_fork_) {
CHECK(B->get_source_id() != local_idx_);
@@ -339,13 +390,13 @@ void CatChainReceiverImpl::add_block(td::BufferSlice payload, std::vectorexport_tl_dep();
}
- auto height = prev->height_ + 1;
+ int height = prev->height_ + 1;
auto block_data = create_tl_object(std::move(prev), std::move(deps_arr));
auto block = create_tl_object(incarnation_, local_idx_, height, std::move(block_data),
td::BufferSlice());
auto id = CatChainReceivedBlock::block_id(this, block, payload);
- auto id_s = serialize_tl_object(id, true);
+ td::BufferSlice id_s = serialize_tl_object(id, true);
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), print_id = print_id(), block = std::move(block),
payload = std::move(payload)](td::Result R) mutable {
@@ -362,24 +413,24 @@ void CatChainReceiverImpl::add_block(td::BufferSlice payload, std::vector block, td::BufferSlice payload) {
validate_block_sync(block, payload.as_slice()).ensure();
- auto B = create_block(std::move(block), td::SharedSlice{payload.as_slice()});
+ CatChainReceivedBlock *B = create_block(std::move(block), td::SharedSlice{payload.as_slice()});
B->written();
run_scheduler();
CHECK(B->delivered());
active_send_ = false;
- if (pending_blocks_.size() > 0) {
- auto B = std::move(pending_blocks_.front());
+ if (!pending_blocks_.empty()) {
+ auto pending_block = std::move(pending_blocks_.front());
pending_blocks_.pop_front();
- add_block(std::move(B->payload_), std::move(B->deps_));
+ add_block(std::move(pending_block->payload_), std::move(pending_block->deps_));
}
}
void CatChainReceiverImpl::debug_add_fork(td::BufferSlice payload, CatChainBlockHeight height,
std::vector deps) {
intentional_fork_ = true;
- auto S = get_source_by_hash(local_id_);
+ CatChainReceiverSource *S = get_source_by_hash(local_id_);
CHECK(S != nullptr);
CHECK(S->get_id() == local_idx_);
@@ -399,7 +450,7 @@ void CatChainReceiverImpl::debug_add_fork(td::BufferSlice payload, CatChainBlock
std::vector> deps_arr;
deps_arr.resize(deps.size());
for (size_t i = 0; i < deps.size(); i++) {
- auto B = get_block(deps[i]);
+ CatChainReceivedBlock *B = get_block(deps[i]);
LOG_CHECK(B != nullptr) << this << ": cannot find block with hash " << deps[i];
CHECK(B->get_source_id() != local_idx_);
deps_arr[i] = B->export_tl_dep();
@@ -410,7 +461,7 @@ void CatChainReceiverImpl::debug_add_fork(td::BufferSlice payload, CatChainBlock
td::BufferSlice());
auto id = CatChainReceivedBlock::block_id(this, block, payload);
- auto id_s = serialize_tl_object(id, true);
+ td::BufferSlice id_s = serialize_tl_object(id, true);
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), print_id = print_id(), block = std::move(block),
payload = std::move(payload)](td::Result R) mutable {
@@ -425,29 +476,33 @@ void CatChainReceiverImpl::debug_add_fork(td::BufferSlice payload, CatChainBlock
td::actor::send_closure_later(keyring_, &keyring::Keyring::sign_message, local_id_, std::move(id_s), std::move(P));
}
-CatChainReceiverImpl::CatChainReceiverImpl(std::unique_ptr callback, CatChainOptions opts,
+CatChainReceiverImpl::CatChainReceiverImpl(std::unique_ptr callback,
+ const CatChainOptions &opts,
td::actor::ActorId keyring,
td::actor::ActorId adnl,
td::actor::ActorId overlay_manager,
- std::vector ids, PublicKeyHash local_id,
- CatChainSessionId unique_hash, std::string db_root, std::string db_suffix,
+ const std::vector &ids,
+ const PublicKeyHash &local_id,
+ const CatChainSessionId &unique_hash,
+ std::string db_root,
+ std::string db_suffix,
bool allow_unsafe_self_blocks_resync)
: callback_(std::move(callback))
- , opts_(std::move(opts))
- , keyring_(keyring)
- , adnl_(adnl)
- , overlay_manager_(overlay_manager)
+ , opts_(opts)
+ , keyring_(std::move(keyring))
+ , adnl_(std::move(adnl))
+ , overlay_manager_(std::move(overlay_manager))
, local_id_(local_id)
- , db_root_(db_root)
- , db_suffix_(db_suffix)
+ , db_root_(std::move(db_root))
+ , db_suffix_(std::move(db_suffix))
, allow_unsafe_self_blocks_resync_(allow_unsafe_self_blocks_resync) {
std::vector short_ids;
local_idx_ = static_cast(ids.size());
- for (auto &id : ids) {
- td::uint32 seq = static_cast(sources_.size());
+ for (const CatChainNode &id : ids) {
+ auto seq = static_cast(sources_.size());
auto R = CatChainReceiverSource::create(this, id.pub_key, id.adnl_id, seq);
auto S = R.move_as_ok();
- auto h = id.pub_key.compute_short_id();
+ PublicKeyHash h = id.pub_key.compute_short_id();
short_ids.push_back(h.bits256_value());
sources_hashes_[h] = seq;
sources_adnl_addrs_[id.adnl_id] = seq;
@@ -477,12 +532,13 @@ CatChainReceiverImpl::CatChainReceiverImpl(std::unique_ptr callback, C
void CatChainReceiverImpl::start_up() {
std::vector ids;
+ ids.reserve(get_sources_cnt());
for (td::uint32 i = 0; i < get_sources_cnt(); i++) {
ids.push_back(get_source(i)->get_adnl_id());
}
std::map root_keys;
for (td::uint32 i = 0; i < get_sources_cnt(); i++) {
- root_keys.emplace(get_source(i)->get_hash(), 16 << 20);
+ root_keys.emplace(get_source(i)->get_hash(), OVERLAY_MAX_ALLOWED_PACKET_SIZE);
}
td::actor::send_closure(overlay_manager_, &overlay::Overlays::create_private_overlay,
get_source(local_idx_)->get_adnl_id(), overlay_full_id_.clone(), std::move(ids),
@@ -498,13 +554,13 @@ void CatChainReceiverImpl::start_up() {
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result R) {
R.ensure();
- auto g = R.move_as_ok();
+ DbType::GetResult g = R.move_as_ok();
if (g.status == td::KeyValue::GetStatus::NotFound) {
td::actor::send_closure(SelfId, &CatChainReceiverImpl::read_db);
} else {
- auto B = std::move(g.value);
- CHECK(B.size() == 32);
+ td::BufferSlice B = std::move(g.value);
CatChainBlockHash x;
+ CHECK(B.size() == x.as_array().size());
as_slice(x).copy_from(B.as_slice());
td::actor::send_closure(SelfId, &CatChainReceiverImpl::read_db_from, x);
}
@@ -527,7 +583,7 @@ void CatChainReceiverImpl::read_db_from(CatChainBlockHash id) {
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), id](td::Result R) {
R.ensure();
- auto g = R.move_as_ok();
+ DbType::GetResult g = R.move_as_ok();
CHECK(g.status == td::KeyValue::GetStatus::Ok);
td::actor::send_closure(SelfId, &CatChainReceiverImpl::read_block_from_db, id, std::move(g.value));
@@ -543,12 +599,12 @@ void CatChainReceiverImpl::read_block_from_db(CatChainBlockHash id, td::BufferSl
F.ensure();
auto block = F.move_as_ok();
- auto payload = std::move(data);
+ td::BufferSlice payload = std::move(data);
- auto block_id = CatChainReceivedBlock::block_hash(this, block, payload);
+ CatChainBlockHash block_id = CatChainReceivedBlock::block_hash(this, block, payload);
CHECK(block_id == id);
- auto B = get_block(id);
+ CatChainReceivedBlock *B = get_block(id);
if (B && B->initialized()) {
CHECK(B->in_db());
if (!pending_in_db_) {
@@ -557,7 +613,7 @@ void CatChainReceiverImpl::read_block_from_db(CatChainBlockHash id, td::BufferSl
return;
}
- auto source = get_source(block->src_);
+ CatChainReceiverSource *source = get_source(block->src_);
CHECK(source != nullptr);
CHECK(block->incarnation_ == incarnation_);
@@ -565,18 +621,18 @@ void CatChainReceiverImpl::read_block_from_db(CatChainBlockHash id, td::BufferSl
validate_block_sync(block, payload).ensure();
B = create_block(std::move(block), td::SharedSlice{payload.as_slice()});
- B->written();
CHECK(B);
+ B->written();
- auto deps = B->get_dep_hashes();
+ std::vector deps = B->get_dep_hashes();
deps.push_back(B->get_prev_hash());
- for (auto &dep : deps) {
- auto dep_block = get_block(dep);
+ for (const CatChainBlockHash &dep : deps) {
+ CatChainReceivedBlock *dep_block = get_block(dep);
if (!dep_block || !dep_block->initialized()) {
pending_in_db_++;
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), dep](td::Result R) {
R.ensure();
- auto g = R.move_as_ok();
+ DbType::GetResult g = R.move_as_ok();
CHECK(g.status == td::KeyValue::GetStatus::Ok);
td::actor::send_closure(SelfId, &CatChainReceiverImpl::read_block_from_db, dep, std::move(g.value));
@@ -601,26 +657,28 @@ void CatChainReceiverImpl::read_db() {
read_db_ = true;
- next_rotate_ = td::Timestamp::in(60 + td::Random::fast(0, 60));
- next_sync_ = td::Timestamp::in(0.001 * td::Random::fast(0, 60));
- initial_sync_complete_at_ = td::Timestamp::in(allow_unsafe_self_blocks_resync_ ? 300.0 : 5.0);
+ next_rotate_ = td::Timestamp::in(td::Random::fast(NEIGHBOURS_ROTATE_INTERVAL_MIN, NEIGHBOURS_ROTATE_INTERVAL_MAX));
+ next_sync_ = td::Timestamp::in(
+ 0.001 * td::Random::fast(NEIGHBOURS_ROTATE_INTERVAL_MIN, NEIGHBOURS_ROTATE_INTERVAL_MAX));
+ initial_sync_complete_at_ = td::Timestamp::in(
+ allow_unsafe_self_blocks_resync_ ? EXPECTED_UNSAFE_INITIAL_SYNC_DURATION : EXPECTED_INITIAL_SYNC_DURATION);
alarm_timestamp().relax(next_rotate_);
alarm_timestamp().relax(next_sync_);
alarm_timestamp().relax(initial_sync_complete_at_);
}
td::actor::ActorOwn CatChainReceiverInterface::create(
- std::unique_ptr callback, CatChainOptions opts, td::actor::ActorId keyring,
+ std::unique_ptr callback, const CatChainOptions &opts, td::actor::ActorId keyring,
td::actor::ActorId adnl, td::actor::ActorId overlay_manager,
- std::vector ids, PublicKeyHash local_id, CatChainSessionId unique_hash, std::string db_root,
- std::string db_suffix, bool allow_unsafe_self_blocks_resync) {
+ const std::vector &ids, const PublicKeyHash &local_id, const CatChainSessionId &unique_hash,
+ std::string db_root, std::string db_suffix, bool allow_unsafe_self_blocks_resync) {
auto A = td::actor::create_actor(
- "catchainreceiver", std::move(callback), std::move(opts), keyring, adnl, overlay_manager, std::move(ids),
- local_id, unique_hash, db_root, db_suffix, allow_unsafe_self_blocks_resync);
+ "catchainreceiver", std::move(callback), opts, std::move(keyring), std::move(adnl), std::move(overlay_manager),
+ ids, local_id, unique_hash, std::move(db_root), std::move(db_suffix), allow_unsafe_self_blocks_resync);
return std::move(A);
}
-CatChainReceiverSource *CatChainReceiverImpl::get_source_by_hash(PublicKeyHash source_hash) const {
+CatChainReceiverSource *CatChainReceiverImpl::get_source_by_hash(const PublicKeyHash &source_hash) const {
auto it = sources_hashes_.find(source_hash);
if (it == sources_hashes_.end()) {
return nullptr;
@@ -650,10 +708,10 @@ void CatChainReceiverImpl::receive_query_from_overlay(adnl::AdnlNodeIdShort src,
return;
}
auto f = F.move_as_ok();
- ton_api::downcast_call(*f.get(), [&](auto &obj) { this->process_query(src, obj, std::move(promise)); });
+ ton_api::downcast_call(*f, [&](auto &obj) { this->process_query(src, std::move(obj), std::move(promise)); });
}
-void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getBlock &query,
+void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getBlock query,
td::Promise promise) {
auto it = blocks_.find(query.block_);
if (it == blocks_.end() || it->second->get_height() == 0 || !it->second->initialized()) {
@@ -664,19 +722,20 @@ void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::cat
}
}
-void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getBlocks &query,
+void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getBlocks query,
td::Promise promise) {
- if (query.blocks_.size() > 100) {
+ if (query.blocks_.size() > MAX_QUERY_BLOCKS) {
promise.set_error(td::Status::Error(ErrorCode::protoviolation, "too many blocks"));
return;
}
td::int32 cnt = 0;
- for (auto &b : query.blocks_) {
+ for (const CatChainBlockHash &b : query.blocks_) {
auto it = blocks_.find(b);
if (it != blocks_.end() && it->second->get_height() > 0) {
auto block = create_tl_object(it->second->export_tl());
- CHECK(it->second->get_payload().size() > 0);
- auto B = serialize_tl_object(block, true, it->second->get_payload().clone());
+ CHECK(!it->second->get_payload().empty());
+ td::BufferSlice B = serialize_tl_object(block, true, it->second->get_payload().clone());
+ CHECK(B.size() <= opts_.max_serialized_block_size);
td::actor::send_closure(overlay_manager_, &overlay::Overlays::send_message, src,
get_source(local_idx_)->get_adnl_id(), overlay_id_, std::move(B));
cnt++;
@@ -685,19 +744,19 @@ void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::cat
promise.set_value(serialize_tl_object(create_tl_object(cnt), true));
}
-void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getBlockHistory &query,
+void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getBlockHistory query,
td::Promise promise) {
- auto h = query.height_;
+ int64_t h = query.height_;
if (h <= 0) {
promise.set_error(td::Status::Error(ErrorCode::protoviolation, "not-positive height"));
return;
}
- if (h > 100) {
- h = 100;
+ if (h > MAX_QUERY_HEIGHT) {
+ h = MAX_QUERY_HEIGHT;
}
std::set s{query.stop_if_.begin(), query.stop_if_.end()};
- auto B = get_block(query.block_);
+ CatChainReceivedBlock *B = get_block(query.block_);
if (B == nullptr) {
promise.set_value(serialize_tl_object(create_tl_object(0), true));
return;
@@ -711,8 +770,9 @@ void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::cat
break;
}
auto block = create_tl_object(B->export_tl());
- CHECK(B->get_payload().size() > 0);
- auto BB = serialize_tl_object(block, true, B->get_payload().as_slice());
+ CHECK(!B->get_payload().empty());
+ td::BufferSlice BB = serialize_tl_object(block, true, B->get_payload().as_slice());
+ CHECK(BB.size() <= opts_.max_serialized_block_size);
td::actor::send_closure(overlay_manager_, &overlay::Overlays::send_message, src,
get_source(local_idx_)->get_adnl_id(), overlay_id_, std::move(BB));
B = B->get_prev();
@@ -721,7 +781,7 @@ void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::cat
promise.set_value(serialize_tl_object(create_tl_object(cnt), true));
}
-void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getDifference &query,
+void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getDifference query,
td::Promise promise) {
auto &vt = query.rt_;
if (vt.size() != get_sources_cnt()) {
@@ -731,7 +791,7 @@ void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::cat
}
for (td::uint32 i = 0; i < get_sources_cnt(); i++) {
if (vt[i] >= 0) {
- auto S = get_source(i);
+ CatChainReceiverSource *S = get_source(i);
if (S->fork_is_found()) {
auto obj = fetch_tl_object(S->fork_proof(), true);
obj.ensure();
@@ -744,26 +804,21 @@ void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::cat
}
std::vector my_vt(get_sources_cnt());
- td::uint64 total = 0;
for (td::uint32 i = 0; i < get_sources_cnt(); i++) {
if (vt[i] >= 0) {
- auto x = static_cast(vt[i]);
- auto S = get_source(i);
- if (S->delivered_height() > x) {
- total += S->delivered_height() - x;
- }
- my_vt[i] = S->delivered_height();
+ CatChainReceiverSource *S = get_source(i);
+ my_vt[i] = static_cast(S->delivered_height());
} else {
my_vt[i] = -1;
}
}
- const td::uint32 max_send = 100;
+ const td::uint32 max_send = GET_DIFFERENCE_MAX_SEND;
- td::int32 l = 0;
- td::int32 r = max_send + 1;
- while (r - l > 1) {
- td::int32 x = (r + l) / 2;
+ td::int32 left = 0;
+ td::int32 right = max_send + 1;
+ while (right - left > 1) {
+ td::int32 x = (right + left) / 2;
td::uint64 sum = 0;
for (td::uint32 i = 0; i < get_sources_cnt(); i++) {
if (vt[i] >= 0 && my_vt[i] > vt[i]) {
@@ -771,23 +826,23 @@ void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::cat
}
}
if (sum > max_send) {
- r = x;
+ right = x;
} else {
- l = x;
+ left = x;
}
}
- CHECK(r > 0);
+ CHECK(right > 0);
for (td::uint32 i = 0; i < get_sources_cnt(); i++) {
if (vt[i] >= 0 && my_vt[i] > vt[i]) {
- auto S = get_source(i);
- auto t = (my_vt[i] - vt[i] > r) ? r : (my_vt[i] - vt[i]);
- CHECK(t > 0);
+ CatChainReceiverSource *S = get_source(i);
+ td::int32 t = (my_vt[i] - vt[i] > right) ? right : (my_vt[i] - vt[i]);
while (t-- > 0) {
- auto M = S->get_block(++vt[i]);
+ CatChainReceivedBlock *M = S->get_block(++vt[i]);
CHECK(M != nullptr);
auto block = create_tl_object(M->export_tl());
- CHECK(M->get_payload().size() > 0);
- auto BB = serialize_tl_object(block, true, M->get_payload().as_slice());
+ CHECK(!M->get_payload().empty());
+ td::BufferSlice BB = serialize_tl_object(block, true, M->get_payload().as_slice());
+ CHECK(BB.size() <= opts_.max_serialized_block_size);
td::actor::send_closure(overlay_manager_, &overlay::Overlays::send_message, src,
get_source(local_idx_)->get_adnl_id(), overlay_id_, std::move(BB));
}
@@ -798,7 +853,7 @@ void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::cat
}
void CatChainReceiverImpl::got_fork_proof(td::BufferSlice data) {
- auto F = fetch_tl_object(std::move(data), true);
+ auto F = fetch_tl_object(data, true);
if (F.is_error()) {
VLOG(CATCHAIN_WARNING) << this << ": received bad fork proof: " << F.move_as_error();
return;
@@ -825,7 +880,7 @@ void CatChainReceiverImpl::got_fork_proof(td::BufferSlice data) {
return;
}
- auto S = get_source(f->left_->src_);
+ CatChainReceiverSource *S = get_source(f->left_->src_);
S->on_found_fork_proof(
create_serialize_tl_object(std::move(f->left_), std::move(f->right_)));
S->blame();
@@ -835,24 +890,24 @@ void CatChainReceiverImpl::synchronize_with(CatChainReceiverSource *S) {
CHECK(!S->blamed());
std::vector rt(get_sources_cnt());
for (td::uint32 i = 0; i < get_sources_cnt(); i++) {
- auto SS = get_source(i);
+ CatChainReceiverSource *SS = get_source(i);
if (SS->blamed()) {
rt[i] = -1;
} else {
- rt[i] = S->delivered_height();
+ rt[i] = static_cast(S->delivered_height());
}
}
auto P = td::PromiseCreator::lambda(
[SelfId = actor_id(this), src = S->get_hash(), print_id = print_id()](td::Result R) {
if (R.is_error()) {
- VLOG(CATCHAIN_INFO) << print_id << ": timedout syncronize query to " << src;
+ VLOG(CATCHAIN_INFO) << print_id << ": timedout synchronize query to " << src;
return;
}
- auto data = R.move_as_ok();
+ td::BufferSlice data = R.move_as_ok();
auto X = fetch_tl_object(data.clone(), true);
if (X.is_error()) {
- VLOG(CATCHAIN_WARNING) << print_id << ": received incorrect answer to syncronize query from " << src << ": "
+ VLOG(CATCHAIN_WARNING) << print_id << ": received incorrect answer to synchronize query from " << src << ": "
<< X.move_as_error();
return;
}
@@ -866,49 +921,49 @@ void CatChainReceiverImpl::synchronize_with(CatChainReceiverSource *S) {
});
td::actor::send_closure(overlay_manager_, &overlay::Overlays::send_query, S->get_adnl_id(),
get_source(local_idx_)->get_adnl_id(), overlay_id_, "sync", std::move(P),
- td::Timestamp::in(5.0),
+ td::Timestamp::in(GET_DIFFERENCE_TIMEOUT),
serialize_tl_object(create_tl_object(std::move(rt)), true));
if (S->delivered_height() < S->received_height()) {
- auto B = S->get_block(S->delivered_height() + 1);
+ CatChainReceivedBlock *B = S->get_block(S->delivered_height() + 1);
CHECK(B->initialized());
std::vector vec;
- B->find_pending_deps(vec, 16);
+ B->find_pending_deps(vec, MAX_PENDING_DEPS);
- for (auto &hash : vec) {
- auto P = td::PromiseCreator::lambda(
+ for (const CatChainBlockHash &hash : vec) {
+ auto PP = td::PromiseCreator::lambda(
[SelfId = actor_id(this), print_id = print_id(), src = S->get_adnl_id()](td::Result R) {
if (R.is_error()) {
- VLOG(CATCHAIN_INFO) << print_id << ": timedout syncronize query to " << src;
+ VLOG(CATCHAIN_INFO) << print_id << ": timedout synchronize query to " << src;
} else {
td::actor::send_closure(SelfId, &CatChainReceiverImpl::receive_block_answer, src, R.move_as_ok());
}
});
- auto query = serialize_tl_object(create_tl_object(hash), true);
+ td::BufferSlice query = serialize_tl_object(create_tl_object(hash), true);
td::actor::send_closure(overlay_manager_, &overlay::Overlays::send_query, S->get_adnl_id(),
- get_source(local_idx_)->get_adnl_id(), overlay_id_, "sync blocks", std::move(P),
- td::Timestamp::in(2.0), std::move(query));
+ get_source(local_idx_)->get_adnl_id(), overlay_id_, "sync blocks", std::move(PP),
+ td::Timestamp::in(GET_BLOCK_TIMEOUT), std::move(query));
}
}
}
void CatChainReceiverImpl::choose_neighbours() {
std::vector n;
- n.resize(get_max_neighbours());
+ n.resize(MAX_NEIGHBOURS);
td::uint32 size = 0;
for (td::uint32 i = 0; i < get_sources_cnt(); i++) {
if (i == local_idx_) {
continue;
}
- auto S = get_source(i);
+ CatChainReceiverSource *S = get_source(i);
if (!S->blamed()) {
size++;
if (size <= n.size()) {
n[size - 1] = i;
} else {
- td::uint32 id = td::Random::fast(0, size - 1);
+ td::uint32 id = td::Random::fast(0, static_cast(size) - 1);
if (id < n.size()) {
n[id] = i;
}
@@ -922,15 +977,15 @@ void CatChainReceiverImpl::choose_neighbours() {
}
bool CatChainReceiverImpl::unsafe_start_up_check_completed() {
- auto S = get_source(local_idx_);
+ CatChainReceiverSource *S = get_source(local_idx_);
CHECK(!S->blamed());
if (S->has_unreceived() || S->has_undelivered()) {
LOG(INFO) << "catchain: has_unreceived=" << S->has_unreceived() << " has_undelivered=" << S->has_undelivered();
run_scheduler();
- initial_sync_complete_at_ = td::Timestamp::in(60.0);
+ initial_sync_complete_at_ = td::Timestamp::in(EXPECTED_INITIAL_SYNC_DURATION_WITH_UNPROCESSED);
return false;
}
- auto h = S->delivered_height();
+ CatChainBlockHeight h = S->delivered_height();
if (h == 0) {
CHECK(last_sent_block_->get_height() == 0);
CHECK(!unsafe_root_block_writing_);
@@ -941,20 +996,20 @@ bool CatChainReceiverImpl::unsafe_start_up_check_completed() {
return true;
}
if (unsafe_root_block_writing_) {
- initial_sync_complete_at_ = td::Timestamp::in(5.0);
+ initial_sync_complete_at_ = td::Timestamp::in(EXPECTED_INITIAL_SYNC_DURATION);
LOG(INFO) << "catchain: writing=true";
return false;
}
unsafe_root_block_writing_ = true;
- auto B = S->get_block(h);
+ CatChainReceivedBlock *B = S->get_block(h);
CHECK(B != nullptr);
CHECK(B->delivered());
CHECK(B->in_db());
- auto id = B->get_hash();
+ CatChainBlockHash id = B->get_hash();
- td::BufferSlice raw_data{32};
+ td::BufferSlice raw_data{id.as_array().size()};
raw_data.as_slice().copy_from(as_slice(id));
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), block = B](td::Result R) mutable {
@@ -963,7 +1018,7 @@ bool CatChainReceiverImpl::unsafe_start_up_check_completed() {
});
db_.set(CatChainBlockHash::zero(), std::move(raw_data), std::move(P), 0);
- initial_sync_complete_at_ = td::Timestamp::in(5.0);
+ initial_sync_complete_at_ = td::Timestamp::in(EXPECTED_INITIAL_SYNC_DURATION);
LOG(INFO) << "catchain: need update root";
return false;
}
@@ -977,9 +1032,9 @@ void CatChainReceiverImpl::written_unsafe_root_block(CatChainReceivedBlock *bloc
void CatChainReceiverImpl::alarm() {
alarm_timestamp() = td::Timestamp::never();
if (next_sync_ && next_sync_.is_in_past()) {
- next_sync_ = td::Timestamp::in(td::Random::fast(0.1, 0.2));
- for (auto i = 0; i < 3; i++) {
- auto S = get_source(td::Random::fast(0, get_sources_cnt() - 1));
+ next_sync_ = td::Timestamp::in(td::Random::fast(SYNC_INTERVAL_MIN, SYNC_INTERVAL_MAX));
+ for (unsigned i = 0; i < SYNC_ITERATIONS; i++) {
+ CatChainReceiverSource *S = get_source(td::Random::fast(0, static_cast(get_sources_cnt()) - 1));
CHECK(S != nullptr);
if (!S->blamed()) {
synchronize_with(S);
@@ -988,7 +1043,7 @@ void CatChainReceiverImpl::alarm() {
}
}
if (next_rotate_ && next_rotate_.is_in_past()) {
- next_rotate_ = td::Timestamp::in(td::Random::fast(60.0, 120.0));
+ next_rotate_ = td::Timestamp::in(td::Random::fast(NEIGHBOURS_ROTATE_INTERVAL_MIN, NEIGHBOURS_ROTATE_INTERVAL_MAX));
choose_neighbours();
}
if (!started_ && read_db_ && initial_sync_complete_at_ && initial_sync_complete_at_.is_in_past()) {
@@ -1013,58 +1068,68 @@ void CatChainReceiverImpl::send_fec_broadcast(td::BufferSlice data) {
td::actor::send_closure(overlay_manager_, &overlay::Overlays::send_broadcast_fec_ex,
get_source(local_idx_)->get_adnl_id(), overlay_id_, local_id_, 0, std::move(data));
}
-void CatChainReceiverImpl::send_custom_query_data(PublicKeyHash dst, std::string name,
+void CatChainReceiverImpl::send_custom_query_data(const PublicKeyHash &dst, std::string name,
td::Promise promise, td::Timestamp timeout,
td::BufferSlice query) {
- auto S = get_source_by_hash(dst);
+ CatChainReceiverSource *S = get_source_by_hash(dst);
+ CHECK(S != nullptr);
td::actor::send_closure(overlay_manager_, &overlay::Overlays::send_query, S->get_adnl_id(),
get_source(local_idx_)->get_adnl_id(), overlay_id_, std::move(name), std::move(promise),
timeout, std::move(query));
}
-void CatChainReceiverImpl::send_custom_query_data_via(PublicKeyHash dst, std::string name,
+void CatChainReceiverImpl::send_custom_query_data_via(const PublicKeyHash &dst, std::string name,
td::Promise promise, td::Timestamp timeout,
td::BufferSlice query, td::uint64 max_answer_size,
td::actor::ActorId via) {
- auto S = get_source_by_hash(dst);
+ CatChainReceiverSource *S = get_source_by_hash(dst);
+ CHECK(S != nullptr);
td::actor::send_closure(overlay_manager_, &overlay::Overlays::send_query_via, S->get_adnl_id(),
get_source(local_idx_)->get_adnl_id(), overlay_id_, std::move(name), std::move(promise),
timeout, std::move(query), max_answer_size, via);
}
-void CatChainReceiverImpl::send_custom_message_data(PublicKeyHash dst, td::BufferSlice data) {
- auto S = get_source_by_hash(dst);
+void CatChainReceiverImpl::send_custom_message_data(const PublicKeyHash &dst, td::BufferSlice data) {
+ CatChainReceiverSource *S = get_source_by_hash(dst);
+ CHECK(S != nullptr);
td::actor::send_closure(overlay_manager_, &overlay::Overlays::send_message, S->get_adnl_id(),
get_source(local_idx_)->get_adnl_id(), overlay_id_, std::move(data));
}
void CatChainReceiverImpl::block_written_to_db(CatChainBlockHash hash) {
- auto block = get_block(hash);
+ CatChainReceivedBlock *block = get_block(hash);
CHECK(block);
block->written();
run_scheduler();
}
-static void destroy_db(std::string name, td::uint32 attempt) {
+static void destroy_db(const std::string& name, td::uint32 attempt) {
auto S = td::RocksDb::destroy(name);
if (S.is_ok()) {
return;
}
- if (S.is_error() && attempt >= 10) {
- LOG(ERROR) << "failed to destroy catchain " << name << ": " << S;
- } else {
+ if (S.is_error()) {
LOG(DEBUG) << "failed to destroy catchain " << name << ": " << S;
- delay_action([name, attempt]() { destroy_db(name, attempt); }, td::Timestamp::in(1.0));
+ if (attempt < DESTROY_DB_MAX_ATTEMPTS) {
+ delay_action([name, attempt]() { destroy_db(name, attempt + 1); }, td::Timestamp::in(DESTROY_DB_DELAY));
+ }
}
}
void CatChainReceiverImpl::destroy() {
auto name = db_root_ + "/catchainreceiver" + db_suffix_ + td::base64url_encode(as_slice(incarnation_));
- delay_action([name]() { destroy_db(name, 0); }, td::Timestamp::in(1.0));
+ delay_action([name]() { destroy_db(name, 0); }, td::Timestamp::in(DESTROY_DB_DELAY));
stop();
}
+td::uint64 get_max_block_height(const CatChainOptions& opts, size_t sources_cnt) {
+ if (opts.max_block_height_coeff == 0) {
+ return std::numeric_limits::max();
+ }
+ return opts.max_block_height_coeff * (1 + (sources_cnt + opts.max_deps - 1) / opts.max_deps) / 1000;
+}
+
} // namespace catchain
} // namespace ton
diff --git a/catchain/catchain-receiver.h b/catchain/catchain-receiver.h
index c3bae8e0..2c959fbc 100644
--- a/catchain/catchain-receiver.h
+++ b/catchain/catchain-receiver.h
@@ -44,9 +44,6 @@ class CatChainReceiver : public CatChainReceiverInterface {
CatChainSessionId instance_;
PublicKeyHash local_id_;
};
- td::uint32 get_max_neighbours() const {
- return 5;
- }
virtual PrintId print_id() const = 0;
virtual CatChainReceivedBlock *create_block(tl_object_ptr block,
td::SharedSlice payload) = 0;
@@ -64,12 +61,15 @@ class CatChainReceiver : public CatChainReceiverInterface {
virtual const CatChainOptions &opts() const = 0;
- virtual td::Status validate_block_sync(tl_object_ptr &dep) = 0;
- virtual td::Status validate_block_sync(tl_object_ptr &block, td::Slice payload) = 0;
+ virtual td::Status validate_block_sync(const tl_object_ptr &dep) const = 0;
+ virtual td::Status validate_block_sync(const tl_object_ptr &block,
+ const td::Slice &payload) const = 0;
virtual ~CatChainReceiver() = default;
};
+td::uint64 get_max_block_height(const CatChainOptions& opts, size_t sources_cnt);
+
} // namespace catchain
} // namespace ton
diff --git a/catchain/catchain-receiver.hpp b/catchain/catchain-receiver.hpp
index b41c8af0..5da4001c 100644
--- a/catchain/catchain-receiver.hpp
+++ b/catchain/catchain-receiver.hpp
@@ -33,7 +33,7 @@ namespace ton {
namespace catchain {
-class CatChainReceiverImpl : public CatChainReceiver {
+class CatChainReceiverImpl final : public CatChainReceiver {
public:
PrintId print_id() const override {
return PrintId{incarnation_, local_id_};
@@ -62,7 +62,7 @@ class CatChainReceiverImpl : public CatChainReceiver {
return sources_[source_id].get();
}
PublicKeyHash get_source_hash(td::uint32 source_id) const override;
- CatChainReceiverSource *get_source_by_hash(PublicKeyHash source_hash) const;
+ CatChainReceiverSource *get_source_by_hash(const PublicKeyHash &source_hash) const;
CatChainReceiverSource *get_source_by_adnl_id(adnl::AdnlNodeIdShort source_hash) const;
td::uint32 add_fork() override;
@@ -72,39 +72,39 @@ class CatChainReceiverImpl : public CatChainReceiver {
void receive_message_from_overlay(adnl::AdnlNodeIdShort src, td::BufferSlice data);
void receive_query_from_overlay(adnl::AdnlNodeIdShort src, td::BufferSlice data,
td::Promise promise);
- void process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getBlock &query,
+ void process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getBlock query, td::Promise promise);
+ void process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getBlocks query,
td::Promise promise);
- void process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getBlocks &query,
+ void process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getBlockHistory query,
td::Promise promise);
- void process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getBlockHistory &query,
- td::Promise promise);
- void process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getDifference &query,
+ void process_query(adnl::AdnlNodeIdShort src, ton_api::catchain_getDifference query,
td::Promise promise);
template
- void process_query(adnl::AdnlNodeIdShort src, T &query, td::Promise promise) {
+ void process_query(adnl::AdnlNodeIdShort src, const T &query, td::Promise promise) {
//LOG(WARNING) << this << ": unknown query from " << src;
callback_->on_custom_query(get_source_by_adnl_id(src)->get_hash(), serialize_tl_object(&query, true),
std::move(promise));
}
- void receive_broadcast_from_overlay(PublicKeyHash src, td::BufferSlice data);
+ void receive_broadcast_from_overlay(const PublicKeyHash &src, td::BufferSlice data);
void receive_block(adnl::AdnlNodeIdShort src, tl_object_ptr block, td::BufferSlice payload);
void receive_block_answer(adnl::AdnlNodeIdShort src, td::BufferSlice);
- //void send_block(PublicKeyHash src, tl_object_ptr block, td::BufferSlice payload);
+ //void send_block(const PublicKeyHash &src, tl_object_ptr block, td::BufferSlice payload);
CatChainReceivedBlock *create_block(tl_object_ptr block, td::SharedSlice payload) override;
CatChainReceivedBlock *create_block(tl_object_ptr block) override;
- td::Status validate_block_sync(tl_object_ptr &dep) override;
- td::Status validate_block_sync(tl_object_ptr &block, td::Slice payload) override;
+ td::Status validate_block_sync(const tl_object_ptr &dep) const override;
+ td::Status validate_block_sync(const tl_object_ptr &block,
+ const td::Slice &payload) const override;
void send_fec_broadcast(td::BufferSlice data) override;
- void send_custom_query_data(PublicKeyHash dst, std::string name, td::Promise promise,
+ void send_custom_query_data(const PublicKeyHash &dst, std::string name, td::Promise promise,
td::Timestamp timeout, td::BufferSlice query) override;
- void send_custom_query_data_via(PublicKeyHash dst, std::string name, td::Promise promise,
+ void send_custom_query_data_via(const PublicKeyHash &dst, std::string name, td::Promise promise,
td::Timestamp timeout, td::BufferSlice query, td::uint64 max_answer_size,
td::actor::ActorId via) override;
- void send_custom_message_data(PublicKeyHash dst, td::BufferSlice query) override;
+ void send_custom_message_data(const PublicKeyHash &dst, td::BufferSlice query) override;
void run_scheduler();
void add_block(td::BufferSlice data, std::vector deps) override;
@@ -117,8 +117,6 @@ class CatChainReceiverImpl : public CatChainReceiver {
void on_blame(td::uint32 src) override {
callback_->blame(src);
}
- void blame_node(td::uint32 idx) override {
- }
const CatChainOptions &opts() const override {
return opts_;
}
@@ -141,11 +139,11 @@ class CatChainReceiverImpl : public CatChainReceiver {
CatChainReceivedBlock *get_block(CatChainBlockHash hash) const;
- CatChainReceiverImpl(std::unique_ptr callback, CatChainOptions opts,
+ CatChainReceiverImpl(std::unique_ptr callback, const CatChainOptions &opts,
td::actor::ActorId keyring, td::actor::ActorId adnl,
- td::actor::ActorId, std::vector ids, PublicKeyHash local_id,
- CatChainBlockHash unique_hash, std::string db_root, std::string db_suffix,
- bool allow_unsafe_self_blocks_resync);
+ td::actor::ActorId overlays, const std::vector &ids,
+ const PublicKeyHash &local_id, const CatChainBlockHash &unique_hash, std::string db_root,
+ std::string db_suffix, bool allow_unsafe_self_blocks_resync);
private:
std::unique_ptr make_callback() {
@@ -164,7 +162,7 @@ class CatChainReceiverImpl : public CatChainReceiver {
void receive_broadcast(PublicKeyHash src, overlay::OverlayIdShort overlay_id, td::BufferSlice data) override {
td::actor::send_closure(id_, &CatChainReceiverImpl::receive_broadcast_from_overlay, src, std::move(data));
}
- Callback(td::actor::ActorId id) : id_(std::move(id)) {
+ explicit Callback(td::actor::ActorId id) : id_(std::move(id)) {
}
private:
@@ -199,7 +197,7 @@ class CatChainReceiverImpl : public CatChainReceiver {
CatChainReceivedBlock *root_block_;
CatChainReceivedBlock *last_sent_block_;
- CatChainSessionId incarnation_;
+ CatChainSessionId incarnation_{};
std::unique_ptr