/* This file is part of TON Blockchain Library. TON Blockchain Library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. TON Blockchain Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with TON Blockchain Library. If not, see . Copyright 2017-2019 Telegram Systems LLP */ #include "overlay-broadcast.hpp" #include "overlay.hpp" #include "keys/encryptor.h" namespace ton { namespace overlay { td::Status BroadcastSimple::check_time() { return overlay_->check_date(date_); } td::Status BroadcastSimple::check_duplicate() { return overlay_->check_delivered(broadcast_hash_); } td::Status BroadcastSimple::check_source() { return overlay_->check_source_eligible(source_, cert_.get(), data_size()); } td::BufferSlice BroadcastSimple::to_sign() { return create_serialize_tl_object(broadcast_hash_, date_); } td::Status BroadcastSimple::check_signature() { TRY_RESULT(encryptor, overlay_->get_encryptor(source_)); return encryptor->check_signature(to_sign().as_slice(), signature_.as_slice()); } td::Status BroadcastSimple::run_checks() { TRY_STATUS(check_time()); TRY_STATUS(check_duplicate()); TRY_STATUS(check_source()); TRY_STATUS(check_signature()); return td::Status::OK(); } td::Status BroadcastSimple::distribute() { auto B = serialize(); auto nodes = overlay_->get_neighbours(3); auto manager = overlay_->overlay_manager(); for (auto &n : nodes) { td::actor::send_closure(manager, &OverlayManager::send_message, n, overlay_->local_id(), overlay_->overlay_id(), B.clone()); } return td::Status::OK(); } tl_object_ptr BroadcastSimple::tl() const { return create_tl_object(source_.tl(), cert_ ? cert_->tl() : Certificate::empty_tl(), flags_, data_.clone(), date_, signature_.clone()); } td::BufferSlice BroadcastSimple::serialize() { return serialize_tl_object(tl(), true); } td::Status BroadcastSimple::create(OverlayImpl *overlay, tl_object_ptr broadcast) { auto src = PublicKey{broadcast->src_}; auto data_hash = sha256_bits256(broadcast->data_.as_slice()); auto broadcast_hash = compute_broadcast_id(src, data_hash, broadcast->flags_); TRY_STATUS(overlay->check_date(broadcast->date_)); TRY_STATUS(overlay->check_delivered(broadcast_hash)); TRY_RESULT(cert, Certificate::create(std::move(broadcast->certificate_))); auto B = std::make_unique(broadcast_hash, src, std::move(cert), broadcast->flags_, std::move(broadcast->data_), broadcast->date_, std::move(broadcast->signature_), overlay); TRY_STATUS(B->run()); overlay->register_simple_broadcast(std::move(B)); return td::Status::OK(); } td::Status BroadcastSimple::create_new(td::actor::ActorId overlay, td::actor::ActorId keyring, PublicKeyHash local_id, td::BufferSlice data, td::uint32 flags) { auto data_hash = sha256_bits256(data.as_slice()); auto broadcast_hash = compute_broadcast_id(local_id, data_hash, flags); auto date = static_cast(td::Clocks::system()); auto B = std::make_unique(broadcast_hash, PublicKey{}, nullptr, flags, std::move(data), date, td::BufferSlice{}, nullptr); auto to_sign = B->to_sign(); auto P = td::PromiseCreator::lambda( [id = overlay, B = std::move(B)](td::Result> R) mutable { if (R.is_error()) { td::actor::send_closure(id, &OverlayImpl::failed_to_create_simple_broadcast, R.move_as_error()); return; } auto V = R.move_as_ok(); auto pub_id = V.second; B->update_source(pub_id); B->update_signature(std::move(V.first)); td::actor::send_closure(id, &OverlayImpl::created_simple_broadcast, std::move(B)); }); td::actor::send_closure(keyring, &keyring::Keyring::sign_add_get_public_key, local_id, std::move(to_sign), std::move(P)); return td::Status::OK(); } Overlay::BroadcastHash BroadcastSimple::compute_broadcast_id(PublicKeyHash source, Overlay::BroadcastDataHash data_hash, td::uint32 flags) { auto obj = create_tl_object( (flags & Overlays::BroadcastFlagAnySender()) ? PublicKeyHash::zero().tl() : source.tl(), data_hash, flags); return get_tl_object_sha_bits256(obj); } Overlay::BroadcastHash BroadcastSimple::compute_broadcast_id(PublicKey source, Overlay::BroadcastDataHash data_hash, td::uint32 flags) { return compute_broadcast_id(source.compute_short_id(), data_hash, flags); } void BroadcastSimple::update_overlay(OverlayImpl *overlay) { if (overlay_) { return; } overlay_ = overlay; cert_ = overlay->get_certificate(source_.compute_short_id()); } void BroadcastSimple::deliver() { overlay_->deliver_broadcast(source_.compute_short_id(), data_.clone()); } } // namespace overlay } // namespace ton