Skip to content

Commit 413da6c

Browse files
authored
Cached checked certificates in overlays (#1338)
1 parent f00ff75 commit 413da6c

File tree

4 files changed

+49
-29
lines changed

4 files changed

+49
-29
lines changed

overlay/overlay-manager.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ td::Result<std::shared_ptr<Certificate>> Certificate::create(tl_object_ptr<ton_a
564564
}
565565

566566
BroadcastCheckResult Certificate::check(PublicKeyHash node, OverlayIdShort overlay_id, td::int32 unix_time,
567-
td::uint32 size, bool is_fec) const {
567+
td::uint32 size, bool is_fec, bool skip_check_signature) const {
568568
if (size > max_size_) {
569569
return BroadcastCheckResult::Forbidden;
570570
}
@@ -575,16 +575,16 @@ BroadcastCheckResult Certificate::check(PublicKeyHash node, OverlayIdShort overl
575575
return BroadcastCheckResult::Forbidden;
576576
}
577577

578-
auto R1 = issued_by_.get<PublicKey>().create_encryptor();
579-
if (R1.is_error()) {
580-
return BroadcastCheckResult::Forbidden;
581-
}
582-
auto E = R1.move_as_ok();
583-
584-
auto B = to_sign(overlay_id, node);
585-
586-
if (E->check_signature(B.as_slice(), signature_.as_slice()).is_error()) {
587-
return BroadcastCheckResult::Forbidden;
578+
if (!skip_check_signature) {
579+
auto R1 = issued_by_.get<PublicKey>().create_encryptor();
580+
if (R1.is_error()) {
581+
return BroadcastCheckResult::Forbidden;
582+
}
583+
auto E = R1.move_as_ok();
584+
auto B = to_sign(overlay_id, node);
585+
if (E->check_signature(B.as_slice(), signature_.as_slice()).is_error()) {
586+
return BroadcastCheckResult::Forbidden;
587+
}
588588
}
589589

590590
return (flags_ & CertificateFlags::Trusted) ? BroadcastCheckResult::Allowed : BroadcastCheckResult::NeedCheck;

overlay/overlay.cpp

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -503,37 +503,44 @@ td::Status OverlayImpl::check_date(td::uint32 date) {
503503
return td::Status::OK();
504504
}
505505

506-
BroadcastCheckResult OverlayImpl::check_source_eligible(const PublicKeyHash &source, const Certificate *cert,
506+
BroadcastCheckResult OverlayImpl::check_source_eligible(const PublicKeyHash& source, const Certificate* cert,
507507
td::uint32 size, bool is_fec) {
508508
if (size == 0) {
509509
return BroadcastCheckResult::Forbidden;
510510
}
511-
512511
auto r = rules_.check_rules(source, size, is_fec);
513512
if (!cert || r == BroadcastCheckResult::Allowed) {
514513
return r;
515514
}
515+
td::Bits256 cert_hash = get_tl_object_sha_bits256(cert->tl());
516+
auto cached_cert = checked_certificates_cache_.find(source);
517+
bool cached = cached_cert != checked_certificates_cache_.end() && cached_cert->second->cert_hash == cert_hash;
516518

517-
auto r2 = cert->check(source, overlay_id_, static_cast<td::int32>(td::Clocks::system()), size, is_fec);
519+
auto r2 = cert->check(source, overlay_id_, static_cast<td::int32>(td::Clocks::system()), size, is_fec,
520+
/* skip_check_signature = */ cached);
521+
if (r2 != BroadcastCheckResult::Forbidden) {
522+
if (cached_cert == checked_certificates_cache_.end()) {
523+
cached_cert = checked_certificates_cache_.emplace(
524+
source, std::make_unique<CachedCertificate>(source, cert_hash)).first;
525+
} else {
526+
cached_cert->second->cert_hash = cert_hash;
527+
cached_cert->second->remove();
528+
}
529+
checked_certificates_cache_lru_.put(cached_cert->second.get());
530+
while (checked_certificates_cache_.size() > max_checked_certificates_cache_size_) {
531+
auto to_remove = (CachedCertificate*)checked_certificates_cache_lru_.get();
532+
CHECK(to_remove);
533+
to_remove->remove();
534+
checked_certificates_cache_.erase(to_remove->source);
535+
}
536+
}
518537
r2 = broadcast_check_result_min(r2, rules_.check_rules(cert->issuer_hash(), size, is_fec));
519538
return broadcast_check_result_max(r, r2);
520539
}
521540

522-
BroadcastCheckResult OverlayImpl::check_source_eligible(PublicKey source, const Certificate *cert, td::uint32 size,
541+
BroadcastCheckResult OverlayImpl::check_source_eligible(PublicKey source, const Certificate* cert, td::uint32 size,
523542
bool is_fec) {
524-
if (size == 0) {
525-
return BroadcastCheckResult::Forbidden;
526-
}
527-
auto short_id = source.compute_short_id();
528-
529-
auto r = rules_.check_rules(short_id, size, is_fec);
530-
if (!cert || r == BroadcastCheckResult::Allowed) {
531-
return r;
532-
}
533-
534-
auto r2 = cert->check(short_id, overlay_id_, static_cast<td::int32>(td::Clocks::system()), size, is_fec);
535-
r2 = broadcast_check_result_min(r2, rules_.check_rules(cert->issuer_hash(), size, is_fec));
536-
return broadcast_check_result_max(r, r2);
543+
return check_source_eligible(source.compute_short_id(), cert, size, is_fec);
537544
}
538545

539546
td::Status OverlayImpl::check_delivered(BroadcastHash hash) {

overlay/overlay.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,19 @@ class OverlayImpl : public Overlay {
466466
TrafficStats total_traffic_responses, total_traffic_responses_ctr;
467467

468468
OverlayOptions opts_;
469+
470+
struct CachedCertificate : td::ListNode {
471+
CachedCertificate(PublicKeyHash source, td::Bits256 cert_hash)
472+
: source(source)
473+
, cert_hash(cert_hash) {
474+
}
475+
476+
PublicKeyHash source;
477+
td::Bits256 cert_hash;
478+
};
479+
std::map<PublicKeyHash, std::unique_ptr<CachedCertificate>> checked_certificates_cache_;
480+
td::ListNode checked_certificates_cache_lru_;
481+
size_t max_checked_certificates_cache_size_ = 1000;
469482
};
470483

471484
} // namespace overlay

overlay/overlays.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ class Certificate {
149149
td::BufferSlice to_sign(OverlayIdShort overlay_id, PublicKeyHash issued_to) const;
150150

151151
BroadcastCheckResult check(PublicKeyHash node, OverlayIdShort overlay_id, td::int32 unix_time, td::uint32 size,
152-
bool is_fec) const;
152+
bool is_fec, bool skip_check_signature = false) const;
153153
tl_object_ptr<ton_api::overlay_Certificate> tl() const;
154154
const PublicKey &issuer() const;
155155
const PublicKeyHash issuer_hash() const;

0 commit comments

Comments
 (0)