/* 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 */ #pragma once #include "td/utils/int_types.h" #include "td/utils/SharedSlice.h" #include "adnl/adnl-node-id.hpp" #include "tl-utils/tl-utils.hpp" #include "common/io.hpp" namespace ton { namespace dht { using DhtKeyName = std::string; class DhtKeyId { public: explicit DhtKeyId(td::Bits256 value) : value_(value) { } explicit DhtKeyId(adnl::AdnlNodeIdShort value) : value_(value.bits256_value()) { } DhtKeyId() { } td::Bits256 tl() const { return value_; } bool operator<(const DhtKeyId &with) const { return value_ < with.value_; } bool operator==(const DhtKeyId &with) const { return value_ == with.value_; } bool operator!=(const DhtKeyId &with) const { return value_ != with.value_; } DhtKeyId operator^(const DhtKeyId &with) const { return DhtKeyId{value_ ^ with.value_}; } DhtKeyId operator^(const adnl::AdnlNodeIdShort &with) const { return DhtKeyId{value_ ^ with.bits256_value()}; } bool get_bit(td::uint32 bit) const { return value_[bit]; } td::uint32 count_leading_zeroes() const { return value_.count_leading_zeroes(); } adnl::AdnlNodeIdShort to_adnl() const { return adnl::AdnlNodeIdShort{value_}; } static DhtKeyId zero() { return DhtKeyId{td::Bits256::zero()}; } private: td::Bits256 value_; }; using DhtXoredKeyId = DhtKeyId; class DhtKey { public: static constexpr td::uint32 max_name_length() { return 127; } static constexpr td::uint32 max_index() { return 15; } DhtKey(PublicKeyHash id, DhtKeyName namestr, td::uint32 idx) : id_(std::move(id)), namestr_(std::move(namestr)), idx_(idx) { } static td::Result create(tl_object_ptr key); td::Status check() const; const auto &public_key_hash() const { return id_; } const auto &name() const { return namestr_; } td::uint32 idx() const { return idx_; } tl_object_ptr tl() const; DhtKeyId compute_key_id() const; DhtKey clone() const; private: PublicKeyHash id_; DhtKeyName namestr_; td::uint32 idx_; }; class DhtValue; class DhtUpdateRule { public: virtual ~DhtUpdateRule() = default; virtual td::Status check_value(const DhtValue &value) = 0; virtual td::Status update_value(DhtValue &value, DhtValue &&new_value) = 0; virtual bool need_republish() const = 0; virtual tl_object_ptr tl() const = 0; static td::Result> create(tl_object_ptr obj); }; class DhtKeyDescription { public: DhtKeyDescription(DhtKey key, PublicKey public_key, std::shared_ptr update_rule, td::BufferSlice signature) : key_(std::move(key)) , public_key_(std::move(public_key)) , update_rule_(std::move(update_rule)) , signature_(signature.as_slice()) { } DhtKeyDescription(DhtKey key, PublicKey public_key, std::shared_ptr update_rule, td::SharedSlice signature) : key_(std::move(key)) , public_key_(std::move(public_key)) , update_rule_(std::move(update_rule)) , signature_(std::move(signature)) { } const auto &key() const { return key_; } const auto &public_key() const { return public_key_; } const auto &update_rule() const { return update_rule_; } void update_signature(td::BufferSlice signature); void update_signature(td::SharedSlice signature); td::BufferSlice to_sign() const; td::Status check() const; tl_object_ptr tl() const; DhtKeyDescription clone() const; static td::Result create(tl_object_ptr desc, bool check_signature); static td::Result create(DhtKey key, PublicKey public_key, std::shared_ptr update_rule, td::BufferSlice signature); static td::Result create(DhtKey key, PublicKey public_key, std::shared_ptr update_rule, td::SharedSlice signature); private: DhtKey key_; PublicKey public_key_; std::shared_ptr update_rule_; td::SharedSlice signature_; }; class DhtValue { public: static constexpr td::uint32 max_value_size() { return 768; } DhtValue(DhtKeyDescription key, td::BufferSlice value, td::uint32 ttl, td::BufferSlice signature) : key_(std::move(key)), value_(value.as_slice()), ttl_(ttl), signature_(signature.as_slice()) { } DhtValue(DhtKeyDescription key, td::SharedSlice value, td::uint32 ttl, td::SharedSlice signature) : key_(std::move(key)), value_(std::move(value)), ttl_(ttl), signature_(std::move(signature)) { } static td::Result create(tl_object_ptr obj, bool check_signature); static td::Result create(DhtKeyDescription key, td::BufferSlice value, td::uint32 ttl, td::BufferSlice signature); static td::Result create(DhtKeyDescription key, td::SharedSlice value, td::uint32 ttl, td::SharedSlice signature); const auto &key() const { return key_; } const auto &value() const { return value_; } const auto &signature() const { return signature_; } td::uint32 ttl() const { return ttl_; } bool expired() const { return ttl_ < td::Clocks::system(); } DhtValue clone() const; tl_object_ptr tl() const; td::BufferSlice to_sign() const; td::Status update(DhtValue &&value); void set(td::BufferSlice value, td::uint32 ttl, td::BufferSlice signature); void set(td::SharedSlice value, td::uint32 ttl, td::SharedSlice signature); void update_signature(td::BufferSlice signature); void update_signature(td::SharedSlice signature); td::Status check() const; DhtKeyId key_id() const; private: DhtKeyDescription key_; td::SharedSlice value_; td::uint32 ttl_; td::SharedSlice signature_; }; class DhtUpdateRuleSignature : public DhtUpdateRule { public: td::Status check_value(const DhtValue &value) override; td::Status update_value(DhtValue &value, DhtValue &&new_value) override; bool need_republish() const override { return true; } tl_object_ptr tl() const override; static td::Result> create(); }; class DhtUpdateRuleAnybody : public DhtUpdateRule { public: td::Status check_value(const DhtValue &value) override; td::Status update_value(DhtValue &value, DhtValue &&new_value) override; bool need_republish() const override { return false; } tl_object_ptr tl() const override; static td::Result> create(); }; class DhtUpdateRuleOverlayNodes : public DhtUpdateRule { public: td::Status check_value(const DhtValue &value) override; td::Status update_value(DhtValue &value, DhtValue &&new_value) override; bool need_republish() const override { return false; } tl_object_ptr tl() const override; static td::Result> create(); }; } // namespace dht } // namespace ton namespace td { inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::dht::DhtKeyId &dht) { sb << dht.tl(); return sb; } } // namespace td