1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-15 04:32:21 +00:00

Add overlay certificate checks

This commit is contained in:
OmicronTau 2021-11-13 16:17:17 +03:00 committed by EmelyanenkoK
parent 9e9351903a
commit 678a8a6a13
17 changed files with 232 additions and 62 deletions

View file

@ -486,7 +486,7 @@ void CatChainReceiverImpl::start_up() {
} }
td::actor::send_closure(overlay_manager_, &overlay::Overlays::create_private_overlay, 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), get_source(local_idx_)->get_adnl_id(), overlay_full_id_.clone(), std::move(ids),
make_callback(), overlay::OverlayPrivacyRules{0, std::move(root_keys)}); make_callback(), overlay::OverlayPrivacyRules{0, 0, std::move(root_keys)});
CHECK(root_block_); CHECK(root_block_);

View file

@ -17,8 +17,14 @@
Copyright 2017-2020 Telegram Systems LLP Copyright 2017-2020 Telegram Systems LLP
*/ */
#include "overlay-broadcast.hpp" #include "overlay-broadcast.hpp"
#include "adnl/adnl-node-id.hpp"
#include "common/util.h"
#include "overlay.hpp" #include "overlay.hpp"
#include "keys/encryptor.h" #include "keys/encryptor.h"
#include "td/actor/PromiseFuture.h"
#include "td/actor/actor.h"
#include "td/utils/Status.h"
#include "td/utils/port/Stat.h"
namespace ton { namespace ton {
@ -33,7 +39,13 @@ td::Status BroadcastSimple::check_duplicate() {
} }
td::Status BroadcastSimple::check_source() { td::Status BroadcastSimple::check_source() {
return overlay_->check_source_eligible(source_, cert_.get(), data_size()); auto r = overlay_->check_source_eligible(source_, cert_.get(), data_size(), false);
if (r == BroadcastCheckResult::Forbidden) {
return td::Status::Error(ErrorCode::error, "broadcast is forbidden");
}
is_valid_ = r == BroadcastCheckResult::Allowed;
return td::Status::OK();
} }
td::BufferSlice BroadcastSimple::to_sign() { td::BufferSlice BroadcastSimple::to_sign() {
@ -66,6 +78,14 @@ td::Status BroadcastSimple::distribute() {
return td::Status::OK(); return td::Status::OK();
} }
void BroadcastSimple::broadcast_checked(td::Result<td::Unit> R) {
if (R.is_error()) {
return;
}
is_valid_ = true;
run_continue().ignore();
}
tl_object_ptr<ton_api::overlay_broadcast> BroadcastSimple::tl() const { tl_object_ptr<ton_api::overlay_broadcast> BroadcastSimple::tl() const {
return create_tl_object<ton_api::overlay_broadcast>(source_.tl(), cert_ ? cert_->tl() : Certificate::empty_tl(), return create_tl_object<ton_api::overlay_broadcast>(source_.tl(), cert_ ? cert_->tl() : Certificate::empty_tl(),
flags_, data_.clone(), date_, signature_.clone()); flags_, data_.clone(), date_, signature_.clone());
@ -75,6 +95,25 @@ td::BufferSlice BroadcastSimple::serialize() {
return serialize_tl_object(tl(), true); return serialize_tl_object(tl(), true);
} }
td::Status BroadcastSimple::run_continue() {
TRY_STATUS(distribute());
deliver();
return td::Status::OK();
}
td::Status BroadcastSimple::run() {
TRY_STATUS(run_checks());
if (!is_valid_) {
auto P = td::PromiseCreator::lambda(
[id = broadcast_hash_, overlay_id = actor_id(overlay_)](td::Result<td::Unit> R) mutable {
td::actor::send_closure(std::move(overlay_id), &OverlayImpl::broadcast_checked, id, std::move(R));
});
overlay_->check_broadcast(source_.compute_short_id(), data_.clone(), std::move(P));
return td::Status::OK();
}
return run_continue();
}
td::Status BroadcastSimple::create(OverlayImpl *overlay, tl_object_ptr<ton_api::overlay_broadcast> broadcast) { td::Status BroadcastSimple::create(OverlayImpl *overlay, tl_object_ptr<ton_api::overlay_broadcast> broadcast) {
auto src = PublicKey{broadcast->src_}; auto src = PublicKey{broadcast->src_};
auto data_hash = sha256_bits256(broadcast->data_.as_slice()); auto data_hash = sha256_bits256(broadcast->data_.as_slice());
@ -86,7 +125,7 @@ td::Status BroadcastSimple::create(OverlayImpl *overlay, tl_object_ptr<ton_api::
auto B = std::make_unique<BroadcastSimple>(broadcast_hash, src, std::move(cert), broadcast->flags_, auto B = std::make_unique<BroadcastSimple>(broadcast_hash, src, std::move(cert), broadcast->flags_,
std::move(broadcast->data_), broadcast->date_, std::move(broadcast->data_), broadcast->date_,
std::move(broadcast->signature_), overlay); std::move(broadcast->signature_), false, overlay);
TRY_STATUS(B->run()); TRY_STATUS(B->run());
overlay->register_simple_broadcast(std::move(B)); overlay->register_simple_broadcast(std::move(B));
return td::Status::OK(); return td::Status::OK();
@ -100,7 +139,7 @@ td::Status BroadcastSimple::create_new(td::actor::ActorId<OverlayImpl> overlay,
auto date = static_cast<td::uint32>(td::Clocks::system()); auto date = static_cast<td::uint32>(td::Clocks::system());
auto B = std::make_unique<BroadcastSimple>(broadcast_hash, PublicKey{}, nullptr, flags, std::move(data), date, auto B = std::make_unique<BroadcastSimple>(broadcast_hash, PublicKey{}, nullptr, flags, std::move(data), date,
td::BufferSlice{}, nullptr); td::BufferSlice{}, false, nullptr);
auto to_sign = B->to_sign(); auto to_sign = B->to_sign();
auto P = td::PromiseCreator::lambda( auto P = td::PromiseCreator::lambda(

View file

@ -18,9 +18,16 @@
*/ */
#pragma once #pragma once
#include "adnl/adnl-local-id.h"
#include "adnl/adnl-node-id.hpp"
#include "auto/tl/ton_api.h" #include "auto/tl/ton_api.h"
#include "common/refcnt.hpp"
#include "overlay/overlay.h" #include "overlay/overlay.h"
#include "td/actor/PromiseFuture.h"
#include "td/utils/List.h" #include "td/utils/List.h"
#include "td/utils/Status.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
namespace ton { namespace ton {
@ -38,6 +45,7 @@ class BroadcastSimple : public td::ListNode {
td::BufferSlice data_; td::BufferSlice data_;
td::uint32 date_; td::uint32 date_;
td::BufferSlice signature_; td::BufferSlice signature_;
bool is_valid_{false};
OverlayImpl *overlay_; OverlayImpl *overlay_;
@ -52,7 +60,7 @@ class BroadcastSimple : public td::ListNode {
public: public:
BroadcastSimple(Overlay::BroadcastHash broadcast_hash, PublicKey source, std::shared_ptr<Certificate> cert, BroadcastSimple(Overlay::BroadcastHash broadcast_hash, PublicKey source, std::shared_ptr<Certificate> cert,
td::uint32 flags, td::BufferSlice data, td::uint32 date, td::BufferSlice signature, td::uint32 flags, td::BufferSlice data, td::uint32 date, td::BufferSlice signature, bool is_valid,
OverlayImpl *overlay) OverlayImpl *overlay)
: broadcast_hash_(broadcast_hash) : broadcast_hash_(broadcast_hash)
, source_(std::move(source)) , source_(std::move(source))
@ -61,6 +69,7 @@ class BroadcastSimple : public td::ListNode {
, data_(std::move(data)) , data_(std::move(data))
, date_(date) , date_(date)
, signature_(std::move(signature)) , signature_(std::move(signature))
, is_valid_(is_valid)
, overlay_(overlay) { , overlay_(overlay) {
} }
@ -80,17 +89,14 @@ class BroadcastSimple : public td::ListNode {
} }
void deliver(); void deliver();
td::Status run() { td::Status run();
TRY_STATUS(run_checks()); td::Status run_continue();
TRY_STATUS(distribute());
deliver();
return td::Status::OK();
}
tl_object_ptr<ton_api::overlay_broadcast> tl() const; tl_object_ptr<ton_api::overlay_broadcast> tl() const;
td::BufferSlice serialize(); td::BufferSlice serialize();
void update_overlay(OverlayImpl *overlay); void update_overlay(OverlayImpl *overlay);
void broadcast_checked(td::Result<td::Unit> R);
static td::Status create(OverlayImpl *overlay, tl_object_ptr<ton_api::overlay_broadcast> broadcast); static td::Status create(OverlayImpl *overlay, tl_object_ptr<ton_api::overlay_broadcast> broadcast);
static td::Status create_new(td::actor::ActorId<OverlayImpl> overlay, td::actor::ActorId<keyring::Keyring> keyring, static td::Status create_new(td::actor::ActorId<OverlayImpl> overlay, td::actor::ActorId<keyring::Keyring> keyring,

View file

@ -54,7 +54,16 @@ td::Status OverlayFecBroadcastPart::check_duplicate() {
} }
td::Status OverlayFecBroadcastPart::check_source() { td::Status OverlayFecBroadcastPart::check_source() {
TRY_STATUS(overlay_->check_source_eligible(source_, cert_.get(), broadcast_size_)); auto r = overlay_->check_source_eligible(source_, cert_.get(), broadcast_size_, true);
if (r == BroadcastCheckResult::Forbidden) {
return td::Status::Error(ErrorCode::error, "broadcast is forbidden");
}
// FIXME
if (r == BroadcastCheckResult::NeedCheck) {
return td::Status::Error(ErrorCode::error, "broadcast is forbidden");
}
if (bcast_) { if (bcast_) {
TRY_STATUS(bcast_->is_eligible_sender(source_)); TRY_STATUS(bcast_->is_eligible_sender(source_));
} }

View file

@ -185,6 +185,9 @@ class BroadcastFec : public td::ListNode {
} }
} }
void broadcast_checked(td::Result<td::Unit> R) {
}
private: private:
bool ready_ = false; bool ready_ = false;
@ -311,4 +314,3 @@ class OverlayFecBroadcastPart : public td::ListNode {
} // namespace overlay } // namespace overlay
} // namespace ton } // namespace ton

View file

@ -17,6 +17,7 @@
Copyright 2017-2020 Telegram Systems LLP Copyright 2017-2020 Telegram Systems LLP
*/ */
#include "overlay-manager.h" #include "overlay-manager.h"
#include "auto/tl/ton_api.h"
#include "overlay.h" #include "overlay.h"
#include "adnl/utils.hpp" #include "adnl/utils.hpp"
@ -268,17 +269,21 @@ void OverlayManager::save_to_db(adnl::AdnlNodeIdShort local_id, OverlayIdShort o
db_.set(key, create_serialize_tl_object<ton_api::overlay_db_nodes>(std::move(obj))); db_.set(key, create_serialize_tl_object<ton_api::overlay_db_nodes>(std::move(obj)));
} }
Certificate::Certificate(PublicKey issued_by, td::int32 expire_at, td::uint32 max_size, td::BufferSlice signature) Certificate::Certificate(PublicKey issued_by, td::int32 expire_at, td::uint32 max_size, td::uint32 flags,
td::BufferSlice signature)
: issued_by_(issued_by) : issued_by_(issued_by)
, expire_at_(expire_at) , expire_at_(expire_at)
, max_size_(max_size) , max_size_(max_size)
, flags_(flags)
, signature_(td::SharedSlice(signature.as_slice())) { , signature_(td::SharedSlice(signature.as_slice())) {
} }
Certificate::Certificate(PublicKeyHash issued_by, td::int32 expire_at, td::uint32 max_size, td::BufferSlice signature) Certificate::Certificate(PublicKeyHash issued_by, td::int32 expire_at, td::uint32 max_size, td::uint32 flags,
td::BufferSlice signature)
: issued_by_(issued_by) : issued_by_(issued_by)
, expire_at_(expire_at) , expire_at_(expire_at)
, max_size_(max_size) , max_size_(max_size)
, flags_(flags)
, signature_(td::SharedSlice(signature.as_slice())) { , signature_(td::SharedSlice(signature.as_slice())) {
} }
@ -290,9 +295,19 @@ void Certificate::set_issuer(PublicKey issuer) {
issued_by_ = issuer; issued_by_ = issuer;
} }
constexpr td::uint32 cert_default_flags(td::uint32 max_size) {
return (max_size > Overlays::max_simple_broadcast_size() ? CertificateFlags::AllowFec : 0) |
CertificateFlags::Trusted;
}
td::BufferSlice Certificate::to_sign(OverlayIdShort overlay_id, PublicKeyHash issued_to) const { td::BufferSlice Certificate::to_sign(OverlayIdShort overlay_id, PublicKeyHash issued_to) const {
return create_serialize_tl_object<ton_api::overlay_certificateId>(overlay_id.tl(), issued_to.tl(), expire_at_, if (flags_ == cert_default_flags(max_size_)) {
max_size_); return create_serialize_tl_object<ton_api::overlay_certificateId>(overlay_id.tl(), issued_to.tl(), expire_at_,
max_size_);
} else {
return create_serialize_tl_object<ton_api::overlay_certificateIdV2>(overlay_id.tl(), issued_to.tl(), expire_at_,
max_size_, flags_);
}
} }
const PublicKeyHash Certificate::issuer_hash() const { const PublicKeyHash Certificate::issuer_hash() const {
@ -307,32 +322,48 @@ const PublicKey &Certificate::issuer() const {
td::Result<std::shared_ptr<Certificate>> Certificate::create(tl_object_ptr<ton_api::overlay_Certificate> cert) { td::Result<std::shared_ptr<Certificate>> Certificate::create(tl_object_ptr<ton_api::overlay_Certificate> cert) {
std::shared_ptr<Certificate> res; std::shared_ptr<Certificate> res;
ton_api::downcast_call(*cert.get(), td::overloaded([&](ton_api::overlay_emptyCertificate &obj) { res = nullptr; }, ton_api::downcast_call(*cert.get(),
[&](ton_api::overlay_certificate &obj) { td::overloaded([&](ton_api::overlay_emptyCertificate &obj) { res = nullptr; },
res = std::make_shared<Certificate>( [&](ton_api::overlay_certificate &obj) {
PublicKey{obj.issued_by_}, obj.expire_at_, res = std::make_shared<Certificate>(PublicKey{obj.issued_by_}, obj.expire_at_,
static_cast<td::uint32>(obj.max_size_), static_cast<td::uint32>(obj.max_size_),
std::move(obj.signature_)); cert_default_flags(obj.max_size_),
})); std::move(obj.signature_));
},
[&](ton_api::overlay_certificateV2 &obj) {
res = std::make_shared<Certificate>(PublicKey{obj.issued_by_}, obj.expire_at_,
static_cast<td::uint32>(obj.max_size_),
static_cast<td::uint32>(obj.flags_),
std::move(obj.signature_));
}));
return std::move(res); return std::move(res);
} }
td::Status Certificate::check(PublicKeyHash node, OverlayIdShort overlay_id, td::int32 unix_time, BroadcastCheckResult Certificate::check(PublicKeyHash node, OverlayIdShort overlay_id, td::int32 unix_time,
td::uint32 size) const { td::uint32 size, bool is_fec) const {
if (size > max_size_) { if (size > max_size_) {
return td::Status::Error(ErrorCode::protoviolation, "too big broadcast size"); return BroadcastCheckResult::Forbidden;
} }
if (unix_time > expire_at_) { if (unix_time > expire_at_) {
return td::Status::Error(ErrorCode::protoviolation, "too old certificate"); return BroadcastCheckResult::Forbidden;
}
if (is_fec && !(flags_ & CertificateFlags::AllowFec)) {
return BroadcastCheckResult::Forbidden;
} }
TRY_RESULT(E, issued_by_.get<PublicKey>().create_encryptor()); auto R1 = issued_by_.get<PublicKey>().create_encryptor();
if (R1.is_error()) {
return BroadcastCheckResult::Forbidden;
}
auto E = R1.move_as_ok();
auto B = to_sign(overlay_id, node); auto B = to_sign(overlay_id, node);
TRY_STATUS(E->check_signature(B.as_slice(), signature_.as_slice())); if (E->check_signature(B.as_slice(), signature_.as_slice()).is_error()) {
return BroadcastCheckResult::Forbidden;
}
return td::Status::OK(); return (flags_ & CertificateFlags::Trusted) ? BroadcastCheckResult::Allowed : BroadcastCheckResult::NeedCheck;
} }
tl_object_ptr<ton_api::overlay_Certificate> Certificate::tl() const { tl_object_ptr<ton_api::overlay_Certificate> Certificate::tl() const {

View file

@ -391,25 +391,21 @@ td::Status OverlayImpl::check_date(td::uint32 date) {
return td::Status::OK(); return td::Status::OK();
} }
td::Status OverlayImpl::check_source_eligible(PublicKey source, const Certificate *cert, td::uint32 size) { BroadcastCheckResult OverlayImpl::check_source_eligible(PublicKey source, const Certificate *cert, td::uint32 size,
bool is_fec) {
if (size == 0) { if (size == 0) {
return td::Status::Error(ErrorCode::protoviolation, "empty broadcast"); return BroadcastCheckResult::Forbidden;
} }
auto short_id = source.compute_short_id(); auto short_id = source.compute_short_id();
auto r = rules_.max_size(source.compute_short_id()); auto r = rules_.check_rules(source.compute_short_id(), size, is_fec);
if (r >= size) { if (!cert || r == BroadcastCheckResult::Allowed) {
return td::Status::OK(); return r;
} }
if (!cert) {
return td::Status::Error(ErrorCode::protoviolation, "source is not eligible"); auto r2 = cert->check(short_id, overlay_id_, static_cast<td::int32>(td::Clocks::system()), size, is_fec);
} r2 = broadcast_check_result_min(r2, rules_.check_rules(cert->issuer_hash(), size, is_fec));
TRY_STATUS(cert->check(short_id, overlay_id_, static_cast<td::int32>(td::Clocks::system()), size)); return broadcast_check_result_max(r, r2);
auto issuer_short = cert->issuer_hash();
if (rules_.max_size(issuer_short) < size) {
return td::Status::Error(ErrorCode::protoviolation, "bad certificate");
}
return td::Status::OK();
} }
td::Status OverlayImpl::check_delivered(BroadcastHash hash) { td::Status OverlayImpl::check_delivered(BroadcastHash hash) {
@ -539,6 +535,25 @@ void OverlayImpl::set_privacy_rules(OverlayPrivacyRules rules) {
rules_ = std::move(rules); rules_ = std::move(rules);
} }
void OverlayImpl::check_broadcast(PublicKeyHash src, td::BufferSlice data, td::Promise<td::Unit> promise) {
callback_->check_broadcast(src, overlay_id_, std::move(data), std::move(promise));
}
void OverlayImpl::broadcast_checked(Overlay::BroadcastHash hash, td::Result<td::Unit> R) {
{
auto it = broadcasts_.find(hash);
if (it != broadcasts_.end()) {
it->second->broadcast_checked(std::move(R));
}
}
{
auto it = fec_broadcasts_.find(hash);
if (it != fec_broadcasts_.end()) {
it->second->broadcast_checked(std::move(R));
}
}
}
} // namespace overlay } // namespace overlay
} // namespace ton } // namespace ton

View file

@ -144,9 +144,12 @@ class OverlayImpl : public Overlay {
void print(td::StringBuilder &sb) override; void print(td::StringBuilder &sb) override;
td::Status check_date(td::uint32 date); td::Status check_date(td::uint32 date);
td::Status check_source_eligible(PublicKey source, const Certificate *cert, td::uint32 size); BroadcastCheckResult check_source_eligible(PublicKey source, const Certificate *cert, td::uint32 size, bool is_fec);
td::Status check_delivered(BroadcastHash hash); td::Status check_delivered(BroadcastHash hash);
void broadcast_checked(Overlay::BroadcastHash hash, td::Result<td::Unit> R);
void check_broadcast(PublicKeyHash src, td::BufferSlice data, td::Promise<td::Unit> promise);
BroadcastFec *get_fec_broadcast(BroadcastHash hash); BroadcastFec *get_fec_broadcast(BroadcastHash hash);
void register_fec_broadcast(std::unique_ptr<BroadcastFec> bcast); void register_fec_broadcast(std::unique_ptr<BroadcastFec> bcast);
void register_simple_broadcast(std::unique_ptr<BroadcastSimple> bcast); void register_simple_broadcast(std::unique_ptr<BroadcastSimple> bcast);

View file

@ -21,7 +21,11 @@
#include "adnl/adnl.h" #include "adnl/adnl.h"
#include "dht/dht.h" #include "dht/dht.h"
#include "td/actor/PromiseFuture.h"
#include "td/actor/actor.h" #include "td/actor/actor.h"
#include "td/utils/Status.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include <map> #include <map>
@ -80,41 +84,64 @@ class OverlayIdFull {
td::BufferSlice name_; td::BufferSlice name_;
}; };
struct CertificateFlags {
enum Values : td::uint32 { AllowFec = 1, Trusted = 2 };
};
enum BroadcastCheckResult { Forbidden = 1, NeedCheck = 2, Allowed = 3 };
inline BroadcastCheckResult broadcast_check_result_max(BroadcastCheckResult l, BroadcastCheckResult r) {
return static_cast<BroadcastCheckResult>(std::max(static_cast<td::int32>(l), static_cast<td::int32>(r)));
}
inline BroadcastCheckResult broadcast_check_result_min(BroadcastCheckResult l, BroadcastCheckResult r) {
return static_cast<BroadcastCheckResult>(std::min(static_cast<td::int32>(l), static_cast<td::int32>(r)));
}
class OverlayPrivacyRules { class OverlayPrivacyRules {
public: public:
OverlayPrivacyRules() { OverlayPrivacyRules() {
} }
OverlayPrivacyRules(td::uint32 size) : max_unath_size_(size) { OverlayPrivacyRules(td::uint32 size) : max_unath_size_(size) {
} }
OverlayPrivacyRules(td::uint32 max_size, std::map<PublicKeyHash, td::uint32> authorized_keys) OverlayPrivacyRules(td::uint32 max_size, td::uint32 flags, std::map<PublicKeyHash, td::uint32> authorized_keys)
: max_unath_size_(max_size), authorized_keys_(std::move(authorized_keys)) { : max_unath_size_(max_size), flags_(flags), authorized_keys_(std::move(authorized_keys)) {
} }
td::uint32 max_size(PublicKeyHash hash) { BroadcastCheckResult check_rules(PublicKeyHash hash, td::uint32 size, bool is_fec) {
auto it = authorized_keys_.find(hash); auto it = authorized_keys_.find(hash);
if (it == authorized_keys_.end()) { if (it == authorized_keys_.end()) {
return max_unath_size_; if (size > max_unath_size_) {
return BroadcastCheckResult::Forbidden;
}
if (!(flags_ & CertificateFlags::AllowFec) && is_fec) {
return BroadcastCheckResult::Forbidden;
}
return (flags_ & CertificateFlags::Trusted) ? BroadcastCheckResult::Allowed : BroadcastCheckResult::NeedCheck;
} else { } else {
return it->second; return it->second >= size ? BroadcastCheckResult::Allowed : BroadcastCheckResult::Forbidden;
} }
} }
private: private:
td::uint32 max_unath_size_{0}; td::uint32 max_unath_size_{0};
td::uint32 flags_{0};
std::map<PublicKeyHash, td::uint32> authorized_keys_; std::map<PublicKeyHash, td::uint32> authorized_keys_;
}; };
class Certificate { class Certificate {
public: public:
Certificate(PublicKeyHash issued_by, td::int32 expire_at, td::uint32 max_size, td::BufferSlice signature); Certificate(PublicKeyHash issued_by, td::int32 expire_at, td::uint32 max_size, td::uint32 flags,
Certificate(PublicKey issued_by, td::int32 expire_at, td::uint32 max_size, td::BufferSlice signature); td::BufferSlice signature);
Certificate(PublicKey issued_by, td::int32 expire_at, td::uint32 max_size, td::uint32 flags,
td::BufferSlice signature);
Certificate() { Certificate() {
} }
void set_signature(td::BufferSlice signature); void set_signature(td::BufferSlice signature);
void set_issuer(PublicKey issuer); void set_issuer(PublicKey issuer);
td::BufferSlice to_sign(OverlayIdShort overlay_id, PublicKeyHash issued_to) const; td::BufferSlice to_sign(OverlayIdShort overlay_id, PublicKeyHash issued_to) const;
td::Status check(PublicKeyHash node, OverlayIdShort overlay_id, td::int32 unix_time, td::uint32 size) const; BroadcastCheckResult check(PublicKeyHash node, OverlayIdShort overlay_id, td::int32 unix_time, td::uint32 size,
bool is_fec) const;
tl_object_ptr<ton_api::overlay_Certificate> tl() const; tl_object_ptr<ton_api::overlay_Certificate> tl() const;
const PublicKey &issuer() const; const PublicKey &issuer() const;
const PublicKeyHash issuer_hash() const; const PublicKeyHash issuer_hash() const;
@ -126,6 +153,7 @@ class Certificate {
td::Variant<PublicKey, PublicKeyHash> issued_by_; td::Variant<PublicKey, PublicKeyHash> issued_by_;
td::int32 expire_at_; td::int32 expire_at_;
td::uint32 max_size_; td::uint32 max_size_;
td::uint32 flags_;
td::SharedSlice signature_; td::SharedSlice signature_;
}; };
@ -137,6 +165,10 @@ class Overlays : public td::actor::Actor {
virtual void receive_query(adnl::AdnlNodeIdShort src, OverlayIdShort overlay_id, td::BufferSlice data, virtual void receive_query(adnl::AdnlNodeIdShort src, OverlayIdShort overlay_id, td::BufferSlice data,
td::Promise<td::BufferSlice> promise) = 0; td::Promise<td::BufferSlice> promise) = 0;
virtual void receive_broadcast(PublicKeyHash src, OverlayIdShort overlay_id, td::BufferSlice data) = 0; virtual void receive_broadcast(PublicKeyHash src, OverlayIdShort overlay_id, td::BufferSlice data) = 0;
virtual void check_broadcast(PublicKeyHash src, OverlayIdShort overlay_id, td::BufferSlice data,
td::Promise<td::Unit> promise) {
promise.set_value(td::Unit());
}
virtual ~Callback() = default; virtual ~Callback() = default;
}; };

View file

@ -219,9 +219,11 @@ overlay.broadcastFec.partId broadcast_hash:int256 data_hash:int256 seqno:int = o
overlay.broadcast.toSign hash:int256 date:int = overlay.broadcast.ToSign; overlay.broadcast.toSign hash:int256 date:int = overlay.broadcast.ToSign;
overlay.certificate issued_by:PublicKey expire_at:int max_size:int signature:bytes = overlay.Certificate; overlay.certificate issued_by:PublicKey expire_at:int max_size:int signature:bytes = overlay.Certificate;
overlay.certificateV2 issued_by:PublicKey expire_at:int max_size:int flags:int signature:bytes = overlay.Certificate;
overlay.emptyCertificate = overlay.Certificate; overlay.emptyCertificate = overlay.Certificate;
overlay.certificateId overlay_id:int256 node:int256 expire_at:int max_size:int = overlay.CertificateId; overlay.certificateId overlay_id:int256 node:int256 expire_at:int max_size:int = overlay.CertificateId;
overlay.certificateIdV2 overlay_id:int256 node:int256 expire_at:int max_size:int flags:int = overlay.CertificateId;
overlay.unicast data:bytes = overlay.Broadcast; overlay.unicast data:bytes = overlay.Broadcast;
overlay.broadcast src:PublicKey certificate:overlay.Certificate flags:int data:bytes date:int signature:bytes = overlay.Broadcast; overlay.broadcast src:PublicKey certificate:overlay.Certificate flags:int data:bytes date:int signature:bytes = overlay.Broadcast;

Binary file not shown.

View file

@ -16,6 +16,8 @@
Copyright 2017-2020 Telegram Systems LLP Copyright 2017-2020 Telegram Systems LLP
*/ */
#include "auto/tl/ton_api.h"
#include "overlays.h"
#include "td/utils/SharedSlice.h" #include "td/utils/SharedSlice.h"
#include "full-node-shard.hpp" #include "full-node-shard.hpp"
#include "full-node-shard-queries.hpp" #include "full-node-shard-queries.hpp"
@ -79,6 +81,10 @@ void FullNodeShardImpl::create_overlay() {
void receive_broadcast(PublicKeyHash src, overlay::OverlayIdShort overlay_id, td::BufferSlice data) override { void receive_broadcast(PublicKeyHash src, overlay::OverlayIdShort overlay_id, td::BufferSlice data) override {
td::actor::send_closure(node_, &FullNodeShardImpl::receive_broadcast, src, std::move(data)); td::actor::send_closure(node_, &FullNodeShardImpl::receive_broadcast, src, std::move(data));
} }
void check_broadcast(PublicKeyHash src, overlay::OverlayIdShort overlay_id, td::BufferSlice data,
td::Promise<td::Unit> promise) override {
td::actor::send_closure(node_, &FullNodeShardImpl::check_broadcast, src, std::move(data), std::move(promise));
}
Callback(td::actor::ActorId<FullNodeShardImpl> node) : node_(node) { Callback(td::actor::ActorId<FullNodeShardImpl> node) : node_(node) {
} }
@ -95,6 +101,17 @@ void FullNodeShardImpl::create_overlay() {
} }
} }
void FullNodeShardImpl::check_broadcast(PublicKeyHash src, td::BufferSlice broadcast, td::Promise<td::Unit> promise) {
auto B = fetch_tl_object<ton_api::tonNode_externalMessageBroadcast>(std::move(broadcast), true);
if (B.is_error()) {
return promise.set_error(B.move_as_error_prefix("failed to parse external message broadcast: "));
}
auto q = B.move_as_ok();
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::check_external_message,
std::move(q->message_->data_), std::move(promise));
}
void FullNodeShardImpl::update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise<td::Unit> promise) { void FullNodeShardImpl::update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise<td::Unit> promise) {
td::actor::send_closure(overlays_, &ton::overlay::Overlays::delete_overlay, adnl_id_, overlay_id_); td::actor::send_closure(overlays_, &ton::overlay::Overlays::delete_overlay, adnl_id_, overlay_id_);
adnl_id_ = adnl_id; adnl_id_ = adnl_id;
@ -804,8 +821,9 @@ void FullNodeShardImpl::sign_new_certificate(PublicKeyHash sign_by) {
return; return;
} }
ton::overlay::Certificate cert{sign_by, static_cast<td::int32>(td::Clocks::system() + 3600), ton::overlay::Certificate cert{
overlay::Overlays::max_fec_broadcast_size(), td::BufferSlice{}}; sign_by, static_cast<td::int32>(td::Clocks::system() + 3600), overlay::Overlays::max_fec_broadcast_size(),
overlay::CertificateFlags::Trusted | overlay::CertificateFlags::AllowFec, td::BufferSlice{}};
auto to_sign = cert.to_sign(overlay_id_, local_id_); auto to_sign = cert.to_sign(overlay_id_, local_id_);
auto P = td::PromiseCreator::lambda( auto P = td::PromiseCreator::lambda(
@ -845,7 +863,7 @@ void FullNodeShardImpl::update_validators(std::vector<PublicKeyHash> public_key_
authorized_keys.emplace(key, overlay::Overlays::max_fec_broadcast_size()); authorized_keys.emplace(key, overlay::Overlays::max_fec_broadcast_size());
} }
rules_ = overlay::OverlayPrivacyRules{1 << 14, std::move(authorized_keys)}; rules_ = overlay::OverlayPrivacyRules{1 << 14, 0, std::move(authorized_keys)};
td::actor::send_closure(overlays_, &overlay::Overlays::set_privacy_rules, adnl_id_, overlay_id_, rules_); td::actor::send_closure(overlays_, &overlay::Overlays::set_privacy_rules, adnl_id_, overlay_id_, rules_);
if (update_cert) { if (update_cert) {
@ -949,8 +967,7 @@ void FullNodeShardImpl::update_neighbour_stats(adnl::AdnlNodeIdShort adnl_id, do
} }
} }
void FullNodeShardImpl::got_neighbour_capabilities(adnl::AdnlNodeIdShort adnl_id, double t, void FullNodeShardImpl::got_neighbour_capabilities(adnl::AdnlNodeIdShort adnl_id, double t, td::BufferSlice data) {
td::BufferSlice data) {
auto it = neighbours_.find(adnl_id); auto it = neighbours_.find(adnl_id);
if (it == neighbours_.end()) { if (it == neighbours_.end()) {
return; return;

View file

@ -19,6 +19,8 @@
#pragma once #pragma once
#include "full-node-shard.h" #include "full-node-shard.h"
#include "td/actor/PromiseFuture.h"
#include "td/utils/port/Poll.h"
namespace ton { namespace ton {
@ -139,6 +141,7 @@ class FullNodeShardImpl : public FullNodeShard {
void process_broadcast(PublicKeyHash src, ton_api::tonNode_externalMessageBroadcast &query); void process_broadcast(PublicKeyHash src, ton_api::tonNode_externalMessageBroadcast &query);
void process_broadcast(PublicKeyHash src, ton_api::tonNode_newShardBlockBroadcast &query); void process_broadcast(PublicKeyHash src, ton_api::tonNode_newShardBlockBroadcast &query);
void receive_broadcast(PublicKeyHash src, td::BufferSlice query); void receive_broadcast(PublicKeyHash src, td::BufferSlice query);
void check_broadcast(PublicKeyHash src, td::BufferSlice query, td::Promise<td::Unit> promise);
void send_ihr_message(td::BufferSlice data) override; void send_ihr_message(td::BufferSlice data) override;
void send_external_message(td::BufferSlice data) override; void send_external_message(td::BufferSlice data) override;

View file

@ -124,6 +124,9 @@ class ValidatorManagerImpl : public ValidatorManager {
//void get_block_description(BlockIdExt block_id, td::Promise<BlockDescription> promise) override; //void get_block_description(BlockIdExt block_id, td::Promise<BlockDescription> promise) override;
void new_external_message(td::BufferSlice data) override; void new_external_message(td::BufferSlice data) override;
void check_external_message(td::BufferSlice data, td::Promise<td::Unit> promise) override {
UNREACHABLE();
}
void new_ihr_message(td::BufferSlice data) override; void new_ihr_message(td::BufferSlice data) override;
void new_shard_block(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) override; void new_shard_block(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) override;

View file

@ -144,6 +144,9 @@ class ValidatorManagerImpl : public ValidatorManager {
void get_key_block_proof_link(BlockIdExt block_id, td::Promise<td::BufferSlice> promise) override; void get_key_block_proof_link(BlockIdExt block_id, td::Promise<td::BufferSlice> promise) override;
void new_external_message(td::BufferSlice data) override; void new_external_message(td::BufferSlice data) override;
void check_external_message(td::BufferSlice data, td::Promise<td::Unit> promise) override {
UNREACHABLE();
}
void new_ihr_message(td::BufferSlice data) override; void new_ihr_message(td::BufferSlice data) override;
void new_shard_block(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) override { void new_shard_block(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) override {
UNREACHABLE(); UNREACHABLE();

View file

@ -20,6 +20,8 @@
#include "interfaces/validator-manager.h" #include "interfaces/validator-manager.h"
#include "interfaces/db.h" #include "interfaces/db.h"
#include "td/actor/PromiseFuture.h"
#include "td/utils/port/Poll.h"
#include "validator-group.hpp" #include "validator-group.hpp"
#include "shard-client.hpp" #include "shard-client.hpp"
#include "manager-init.h" #include "manager-init.h"
@ -325,6 +327,9 @@ class ValidatorManagerImpl : public ValidatorManager {
//void get_block_description(BlockIdExt block_id, td::Promise<BlockDescription> promise) override; //void get_block_description(BlockIdExt block_id, td::Promise<BlockDescription> promise) override;
void new_external_message(td::BufferSlice data) override; void new_external_message(td::BufferSlice data) override;
void check_external_message(td::BufferSlice data, td::Promise<td::Unit> promise) override {
promise.set_value(td::Unit());
}
void new_ihr_message(td::BufferSlice data) override; void new_ihr_message(td::BufferSlice data) override;
void new_shard_block(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) override; void new_shard_block(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) override;

View file

@ -94,9 +94,8 @@ struct ValidatorManagerOptions : public td::CntObject {
BlockIdExt zero_block_id, BlockIdExt init_block_id, BlockIdExt zero_block_id, BlockIdExt init_block_id,
std::function<bool(ShardIdFull, CatchainSeqno, ShardCheckMode)> check_shard = [](ShardIdFull, CatchainSeqno, std::function<bool(ShardIdFull, CatchainSeqno, ShardCheckMode)> check_shard = [](ShardIdFull, CatchainSeqno,
ShardCheckMode) { return true; }, ShardCheckMode) { return true; },
bool allow_blockchain_init = false, double sync_blocks_before = 300, bool allow_blockchain_init = false, double sync_blocks_before = 300, double block_ttl = 86400 * 7,
double block_ttl = 86400 * 7, double state_ttl = 3600, double state_ttl = 3600, double archive_ttl = 86400 * 365, double key_proof_ttl = 86400 * 3650,
double archive_ttl = 86400 * 365, double key_proof_ttl = 86400 * 3650,
bool initial_sync_disabled = false); bool initial_sync_disabled = false);
}; };
@ -176,6 +175,7 @@ class ValidatorManagerInterface : public td::actor::Actor {
virtual void write_handle(BlockHandle handle, td::Promise<td::Unit> promise) = 0; virtual void write_handle(BlockHandle handle, td::Promise<td::Unit> promise) = 0;
virtual void new_external_message(td::BufferSlice data) = 0; virtual void new_external_message(td::BufferSlice data) = 0;
virtual void check_external_message(td::BufferSlice data, td::Promise<td::Unit> promise) = 0;
virtual void new_ihr_message(td::BufferSlice data) = 0; virtual void new_ihr_message(td::BufferSlice data) = 0;
virtual void new_shard_block(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) = 0; virtual void new_shard_block(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) = 0;