diff --git a/dht/dht-bucket.cpp b/dht/dht-bucket.cpp index 4f9d75eb..8c1b4dda 100644 --- a/dht/dht-bucket.cpp +++ b/dht/dht-bucket.cpp @@ -66,7 +66,7 @@ td::uint32 DhtBucket::active_cnt() { } td::Status DhtBucket::add_full_node(DhtKeyId id, DhtNode newnode, td::actor::ActorId adnl, - adnl::AdnlNodeIdShort self_id) { + adnl::AdnlNodeIdShort self_id, td::int32 our_network_id) { for (auto &node : active_nodes_) { if (node && node->get_key() == id) { return node->update_value(std::move(newnode), adnl, self_id); @@ -78,7 +78,8 @@ td::Status DhtBucket::add_full_node(DhtKeyId id, DhtNode newnode, td::actor::Act } } - TRY_RESULT_PREFIX(N, DhtRemoteNode::create(std::move(newnode), max_missed_pings_), "failed to add new node: "); + TRY_RESULT_PREFIX(N, DhtRemoteNode::create(std::move(newnode), max_missed_pings_, our_network_id), + "failed to add new node: "); for (auto &node : backup_nodes_) { if (node == nullptr) { diff --git a/dht/dht-bucket.hpp b/dht/dht-bucket.hpp index 812f670d..9c5d82b1 100644 --- a/dht/dht-bucket.hpp +++ b/dht/dht-bucket.hpp @@ -51,7 +51,7 @@ class DhtBucket { } td::uint32 active_cnt(); td::Status add_full_node(DhtKeyId id, DhtNode node, td::actor::ActorId adnl, - adnl::AdnlNodeIdShort self_id); + adnl::AdnlNodeIdShort self_id, td::int32 our_network_id); void check(bool client_only, td::actor::ActorId adnl, td::actor::ActorId node, adnl::AdnlNodeIdShort src); void receive_ping(DhtKeyId id, DhtNode result, td::actor::ActorId adnl, adnl::AdnlNodeIdShort self_id); diff --git a/dht/dht-in.hpp b/dht/dht-in.hpp index fe106b0d..d81f9a71 100644 --- a/dht/dht-in.hpp +++ b/dht/dht-in.hpp @@ -46,6 +46,7 @@ class DhtMemberImpl : public DhtMember { DhtKeyId key_; td::uint32 k_; td::uint32 a_; + td::int32 network_id_{-1}; td::uint32 max_cache_time_ = 60; td::uint32 max_cache_size_ = 100; @@ -138,8 +139,17 @@ class DhtMemberImpl : public DhtMember { public: DhtMemberImpl(adnl::AdnlNodeIdShort id, std::string db_root, td::actor::ActorId keyring, - td::actor::ActorId adnl, td::uint32 k, td::uint32 a = 3, bool client_only = false) - : id_(id), key_{id_}, k_(k), a_(a), db_root_(db_root), keyring_(keyring), adnl_(adnl), client_only_(client_only) { + td::actor::ActorId adnl, td::int32 network_id, td::uint32 k, td::uint32 a = 3, + bool client_only = false) + : id_(id) + , key_{id_} + , k_(k) + , a_(a) + , network_id_(network_id) + , db_root_(db_root) + , keyring_(keyring) + , adnl_(adnl) + , client_only_(client_only) { for (size_t i = 0; i < 256; i++) { buckets_.emplace_back(k_); } diff --git a/dht/dht-node.cpp b/dht/dht-node.cpp index 2b366ab3..409e3f68 100644 --- a/dht/dht-node.cpp +++ b/dht/dht-node.cpp @@ -23,31 +23,46 @@ namespace ton { namespace dht { -td::Status DhtNode::update(tl_object_ptr obj) { +td::Status DhtNode::update(tl_object_ptr obj, td::int32 our_network_id) { if (version_ && obj->version_ <= version_) { return td::Status::Error(ErrorCode::notready, "too old version"); } - auto signature = std::move(obj->signature_); - auto B = serialize_tl_object(obj, true); - + td::BufferSlice signature; + td::int32 network_id = -1; + if (obj->signature_.size() == 64) { + signature = std::move(obj->signature_); + } else if (obj->signature_.size() == 64 + 4) { + signature = td::BufferSlice{obj->signature_.as_slice().remove_prefix(4)}; + network_id = *(td::uint32 *)obj->signature_.as_slice().remove_suffix(64).data(); + } else { + return td::Status::Error(ErrorCode::notready, "invalid length of signature"); + } + if (network_id != our_network_id && network_id != -1 && our_network_id != -1) { + // Remove (network_id != -1 && our_network_id != -1) after network update + return td::Status::Error(ErrorCode::notready, PSTRING() << "wrong network id (expected " << our_network_id + << ", found " << network_id << ")"); + } TRY_RESULT(pub, adnl::AdnlNodeIdFull::create(obj->id_)); TRY_RESULT(addr_list, adnl::AdnlAddressList::create(std::move(obj->addr_list_))); - if (!addr_list.public_only()) { return td::Status::Error(ErrorCode::notready, "dht node must have only public addresses"); } if (!addr_list.size()) { return td::Status::Error(ErrorCode::notready, "dht node must have >0 addresses"); } + DhtNode new_node{std::move(pub), std::move(addr_list), obj->version_, network_id, std::move(signature)}; + TRY_STATUS(new_node.check_signature()); - TRY_RESULT(E, pub.pubkey().create_encryptor()); - TRY_STATUS(E->check_signature(B.as_slice(), signature.as_slice())); - - id_ = pub; - addr_list_ = addr_list; - version_ = obj->version_; - signature_ = td::SharedSlice(signature.as_slice()); + *this = std::move(new_node); + return td::Status::OK(); +} +td::Status DhtNode::check_signature() const { + TRY_RESULT(enc, id_.pubkey().create_encryptor()); + auto node2 = clone(); + node2.signature_ = {}; + TRY_STATUS_PREFIX(enc->check_signature(serialize_tl_object(node2.tl(), true).as_slice(), signature_.as_slice()), + "bad node signature: "); return td::Status::OK(); } diff --git a/dht/dht-node.hpp b/dht/dht-node.hpp index 03f8d134..d5860f91 100644 --- a/dht/dht-node.hpp +++ b/dht/dht-node.hpp @@ -22,6 +22,8 @@ #include "adnl/adnl-address-list.hpp" #include "dht-types.h" +#include "auto/tl/ton_api.hpp" +#include "td/utils/overloaded.h" namespace ton { @@ -32,26 +34,26 @@ class DhtNode { adnl::AdnlNodeIdFull id_; adnl::AdnlAddressList addr_list_; td::int32 version_{0}; + td::int32 network_id_{-1}; td::SharedSlice signature_; public: - DhtNode() { + DhtNode() = default; + DhtNode(adnl::AdnlNodeIdFull id, adnl::AdnlAddressList addr_list, td::int32 version, td::int32 network_id, td::BufferSlice signature) + : id_(id), addr_list_(addr_list), version_(version), network_id_(network_id), signature_(signature.as_slice()) { } - DhtNode(adnl::AdnlNodeIdFull id, adnl::AdnlAddressList addr_list, td::int32 version, td::BufferSlice signature) - : id_(id), addr_list_(addr_list), version_(version), signature_(signature.as_slice()) { + DhtNode(adnl::AdnlNodeIdFull id, adnl::AdnlAddressList addr_list, td::int32 version, td::int32 network_id, td::SharedSlice signature) + : id_(id), addr_list_(addr_list), version_(version), network_id_(network_id), signature_(std::move(signature)) { } - DhtNode(adnl::AdnlNodeIdFull id, adnl::AdnlAddressList addr_list, td::int32 version, td::SharedSlice signature) - : id_(id), addr_list_(addr_list), version_(version), signature_(std::move(signature)) { - } - static td::Result create(tl_object_ptr obj) { + static td::Result create(tl_object_ptr obj, td::int32 our_network_id) { if (obj->version_ == 0) { return td::Status::Error(ErrorCode::protoviolation, "zero version"); } DhtNode n; - TRY_STATUS(n.update(std::move(obj))); + TRY_STATUS(n.update(std::move(obj), our_network_id)); return std::move(n); } - td::Status update(tl_object_ptr obj); + td::Status update(tl_object_ptr obj, td::int32 our_network_id); DhtKeyId get_key() const { CHECK(!id_.empty()); return DhtKeyId{id_.compute_short_id()}; @@ -68,20 +70,30 @@ class DhtNode { } tl_object_ptr tl() const { - return create_tl_object(id_.tl(), addr_list_.tl(), version_, signature_.clone_as_buffer_slice()); + td::BufferSlice signature_ext; + if (network_id_ == -1) { + signature_ext = signature_.clone_as_buffer_slice(); + } else { + signature_ext = td::BufferSlice{4 + signature_.size()}; + td::MutableSlice s = signature_ext.as_slice(); + s.copy_from(td::Slice(reinterpret_cast(&network_id_), 4)); + s.remove_prefix(4); + s.copy_from(signature_.as_slice()); + } + return create_tl_object(id_.tl(), addr_list_.tl(), version_, std::move(signature_ext)); } DhtNode clone() const { - return DhtNode{id_, addr_list_, version_, signature_.clone()}; + return DhtNode{id_, addr_list_, version_, network_id_, signature_.clone()}; } + td::Status check_signature() const; }; class DhtNodesList { public: - DhtNodesList() { - } - DhtNodesList(tl_object_ptr R) { + DhtNodesList() = default; + DhtNodesList(tl_object_ptr R, td::int32 our_network_id) { for (auto &n : R->nodes_) { - auto N = DhtNode::create(std::move(n)); + auto N = DhtNode::create(std::move(n), our_network_id); if (N.is_ok()) { list_.emplace_back(N.move_as_ok()); } else { diff --git a/dht/dht-query.cpp b/dht/dht-query.cpp index 08579415..bc61242d 100644 --- a/dht/dht-query.cpp +++ b/dht/dht-query.cpp @@ -20,14 +20,11 @@ #include "td/utils/tl_storers.h" #include "td/utils/crypto.h" -#include "td/utils/tl_parsers.h" #include "td/utils/Random.h" #include "td/utils/overloaded.h" #include "td/utils/format.h" -#include "keys/encryptor.h" - #include "auto/tl/ton_api.hpp" #include "dht-query.hpp" @@ -123,7 +120,7 @@ void DhtQueryFindNodes::on_result(td::Result R, adnl::AdnlNodeI VLOG(DHT_WARNING) << this << ": incorrect result on dht.findNodes query from " << dst << ": " << Res.move_as_error(); } else { - add_nodes(DhtNodesList{Res.move_as_ok()}); + add_nodes(DhtNodesList{Res.move_as_ok(), our_network_id()}); } finish_query(); } @@ -185,27 +182,29 @@ void DhtQueryFindValue::on_result(td::Result R, adnl::AdnlNodeI auto A = Res.move_as_ok(); ton_api::downcast_call( - *A.get(), td::overloaded( - [&](ton_api::dht_valueFound &v) { - auto valueR = DhtValue::create(std::move(v.value_), true); - if (valueR.is_error()) { - VLOG(DHT_WARNING) << this << ": received incorrect dht answer on find value query from " << dst - << ": " << valueR.move_as_error(); - return; - } - auto value = valueR.move_as_ok(); - if (value.key_id() != key_) { - VLOG(DHT_WARNING) << this << ": received value for bad key on find value query from " << dst; - return; - } - if (!value.check_is_acceptable()) { - send_get_nodes = true; - return; - } - promise_.set_value(std::move(value)); - need_stop = true; - }, - [&](ton_api::dht_valueNotFound &v) { add_nodes(DhtNodesList{std::move(v.nodes_)}); })); + *A, td::overloaded( + [&](ton_api::dht_valueFound &v) { + auto valueR = DhtValue::create(std::move(v.value_), true); + if (valueR.is_error()) { + VLOG(DHT_WARNING) << this << ": received incorrect dht answer on find value query from " << dst + << ": " << valueR.move_as_error(); + return; + } + auto value = valueR.move_as_ok(); + if (value.key_id() != key_) { + VLOG(DHT_WARNING) << this << ": received value for bad key on find value query from " << dst; + return; + } + if (!value.check_is_acceptable()) { + send_get_nodes = true; + return; + } + promise_.set_value(std::move(value)); + need_stop = true; + }, + [&](ton_api::dht_valueNotFound &v) { + add_nodes(DhtNodesList{std::move(v.nodes_), our_network_id()}); + })); if (need_stop) { stop(); } else if (send_get_nodes) { @@ -229,7 +228,7 @@ void DhtQueryFindValue::on_result_nodes(td::Result R, adnl::Adn return; } auto r = Res.move_as_ok(); - add_nodes(DhtNodesList{create_tl_object(std::move(r->nodes_))}); + add_nodes(DhtNodesList{create_tl_object(std::move(r->nodes_)), our_network_id()}); finish_query(); } @@ -238,12 +237,13 @@ void DhtQueryFindValue::finish(DhtNodesList list) { } DhtQueryStore::DhtQueryStore(DhtValue key_value, DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, - DhtNodesList list, td::uint32 k, td::uint32 a, DhtNode self, bool client_only, - td::actor::ActorId node, td::actor::ActorId adnl, + DhtNodesList list, td::uint32 k, td::uint32 a, td::int32 our_network_id, DhtNode self, + bool client_only, td::actor::ActorId node, td::actor::ActorId adnl, td::Promise promise) : print_id_(print_id) , k_(k) , a_(a) + , our_network_id_(our_network_id) , promise_(std::move(promise)) , value_(std::move(key_value)) , list_(std::move(list)) @@ -261,7 +261,8 @@ void DhtQueryStore::start_up() { auto key = value_.key_id(); auto A = td::actor::create_actor("FindNodesQuery", key, print_id_, src_, std::move(list_), k_, a_, - self_.clone(), client_only_, node_, adnl_, std::move(P)); + our_network_id_, self_.clone(), client_only_, node_, adnl_, + std::move(P)); A.release(); } @@ -323,12 +324,13 @@ void DhtQueryStore::store_ready(td::Result R) { DhtQueryRegisterReverseConnection::DhtQueryRegisterReverseConnection( DhtKeyId key_id, adnl::AdnlNodeIdFull client, td::uint32 ttl, td::BufferSlice signature, - DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, DhtNodesList list, td::uint32 k, td::uint32 a, DhtNode self, - bool client_only, td::actor::ActorId node, td::actor::ActorId adnl, - td::Promise promise) + DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, DhtNodesList list, td::uint32 k, td::uint32 a, + td::int32 our_network_id, DhtNode self, bool client_only, td::actor::ActorId node, + td::actor::ActorId adnl, td::Promise promise) : print_id_(print_id) , k_(k) , a_(a) + , our_network_id_(our_network_id) , promise_(std::move(promise)) , key_id_(key_id) , list_(std::move(list)) @@ -346,7 +348,8 @@ void DhtQueryRegisterReverseConnection::start_up() { }); auto A = td::actor::create_actor("FindNodesQuery", key_id_, print_id_, src_, std::move(list_), k_, - a_, self_.clone(), client_only_, node_, adnl_, std::move(P)); + a_, our_network_id_, self_.clone(), client_only_, node_, adnl_, + std::move(P)); A.release(); } @@ -437,7 +440,7 @@ void DhtQueryRequestReversePing::on_result(td::Result R, adnl:: stop(); }, [&](ton_api::dht_clientNotFound &v) { - add_nodes(DhtNodesList{std::move(v.nodes_)}); + add_nodes(DhtNodesList{std::move(v.nodes_), our_network_id()}); finish_query(); })); } diff --git a/dht/dht-query.hpp b/dht/dht-query.hpp index 491bf61d..cf085e25 100644 --- a/dht/dht-query.hpp +++ b/dht/dht-query.hpp @@ -45,7 +45,7 @@ class DhtQuery : public td::actor::Actor { public: DhtQuery(DhtKeyId key, DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, DhtNodesList list, td::uint32 k, - td::uint32 a, DhtNode self, bool client_only, td::actor::ActorId node, + td::uint32 a, td::int32 our_network_id, DhtNode self, bool client_only, td::actor::ActorId node, td::actor::ActorId adnl) : key_(key) , self_(std::move(self)) @@ -54,6 +54,7 @@ class DhtQuery : public td::actor::Actor { , src_(src) , k_(k) , a_(a) + , our_network_id_(our_network_id) , node_(node) , adnl_(adnl) { add_nodes(std::move(list)); @@ -77,6 +78,9 @@ class DhtQuery : public td::actor::Actor { td::uint32 get_k() const { return k_; } + td::int32 our_network_id() const { + return our_network_id_; + } void start_up() override { send_queries(); } @@ -91,6 +95,7 @@ class DhtQuery : public td::actor::Actor { std::set pending_ids_; td::uint32 k_; td::uint32 a_; + td::int32 our_network_id_; td::actor::ActorId node_; td::uint32 active_queries_ = 0; @@ -104,9 +109,10 @@ class DhtQueryFindNodes : public DhtQuery { public: DhtQueryFindNodes(DhtKeyId key, DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, DhtNodesList list, - td::uint32 k, td::uint32 a, DhtNode self, bool client_only, td::actor::ActorId node, - td::actor::ActorId adnl, td::Promise promise) - : DhtQuery(key, print_id, src, std::move(list), k, a, std::move(self), client_only, node, adnl) + td::uint32 k, td::uint32 a, td::int32 our_network_id, DhtNode self, bool client_only, + td::actor::ActorId node, td::actor::ActorId adnl, + td::Promise promise) + : DhtQuery(key, print_id, src, std::move(list), k, a, our_network_id, std::move(self), client_only, node, adnl) , promise_(std::move(promise)) { } void send_one_query(adnl::AdnlNodeIdShort id) override; @@ -123,9 +129,10 @@ class DhtQueryFindValue : public DhtQuery { public: DhtQueryFindValue(DhtKeyId key, DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, DhtNodesList list, - td::uint32 k, td::uint32 a, DhtNode self, bool client_only, td::actor::ActorId node, - td::actor::ActorId adnl, td::Promise promise) - : DhtQuery(key, print_id, src, std::move(list), k, a, std::move(self), client_only, node, adnl) + td::uint32 k, td::uint32 a, td::int32 our_network_id, DhtNode self, bool client_only, + td::actor::ActorId node, td::actor::ActorId adnl, + td::Promise promise) + : DhtQuery(key, print_id, src, std::move(list), k, a, our_network_id, std::move(self), client_only, node, adnl) , promise_(std::move(promise)) { } void send_one_query(adnl::AdnlNodeIdShort id) override; @@ -143,6 +150,7 @@ class DhtQueryStore : public td::actor::Actor { DhtMember::PrintId print_id_; td::uint32 k_; td::uint32 a_; + td::int32 our_network_id_; td::Promise promise_; td::actor::ActorId node_; td::actor::ActorId adnl_; @@ -157,7 +165,7 @@ class DhtQueryStore : public td::actor::Actor { public: DhtQueryStore(DhtValue key_value, DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, DhtNodesList list, - td::uint32 k, td::uint32 a, DhtNode self, bool client_only, td::actor::ActorId node, + td::uint32 k, td::uint32 a, td::int32 our_network_id, DhtNode self, bool client_only, td::actor::ActorId node, td::actor::ActorId adnl, td::Promise promise); void send_stores(td::Result res); void store_ready(td::Result res); @@ -172,6 +180,7 @@ class DhtQueryRegisterReverseConnection : public td::actor::Actor { DhtMember::PrintId print_id_; td::uint32 k_; td::uint32 a_; + td::int32 our_network_id_; td::Promise promise_; td::actor::ActorId node_; td::actor::ActorId adnl_; @@ -188,9 +197,9 @@ class DhtQueryRegisterReverseConnection : public td::actor::Actor { public: DhtQueryRegisterReverseConnection(DhtKeyId key_id, adnl::AdnlNodeIdFull client, td::uint32 ttl, td::BufferSlice signature, DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, - DhtNodesList list, td::uint32 k, td::uint32 a, DhtNode self, bool client_only, - td::actor::ActorId node, td::actor::ActorId adnl, - td::Promise promise); + DhtNodesList list, td::uint32 k, td::uint32 a, td::int32 our_network_id, + DhtNode self, bool client_only, td::actor::ActorId node, + td::actor::ActorId adnl, td::Promise promise); void send_queries(td::Result R); void ready(td::Result R); void start_up() override; @@ -207,10 +216,11 @@ class DhtQueryRequestReversePing : public DhtQuery { public: DhtQueryRequestReversePing(adnl::AdnlNodeIdShort client, adnl::AdnlNode target, td::BufferSlice signature, DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, DhtNodesList list, td::uint32 k, - td::uint32 a, DhtNode self, bool client_only, td::actor::ActorId node, - td::actor::ActorId adnl, td::Promise promise) + td::uint32 a, td::int32 our_network_id, DhtNode self, bool client_only, + td::actor::ActorId node, td::actor::ActorId adnl, + td::Promise promise) : DhtQuery(DhtMember::get_reverse_connection_key(client).compute_key_id(), print_id, src, std::move(list), k, a, - std::move(self), client_only, node, adnl) + our_network_id, std::move(self), client_only, node, adnl) , promise_(std::move(promise)) , query_(create_serialize_tl_object(target.tl(), std::move(signature), client.bits256_value(), k)) { diff --git a/dht/dht-remote-node.cpp b/dht/dht-remote-node.cpp index f1ea2197..e010bbdc 100644 --- a/dht/dht-remote-node.cpp +++ b/dht/dht-remote-node.cpp @@ -20,13 +20,10 @@ #include "td/utils/tl_storers.h" #include "td/utils/crypto.h" -#include "td/utils/tl_parsers.h" #include "td/utils/Random.h" #include "td/utils/format.h" -#include "keys/encryptor.h" - #include "auto/tl/ton_api.hpp" #include "dht-remote-node.hpp" @@ -51,12 +48,7 @@ td::Status DhtRemoteNode::update_value(DhtNode node, td::actor::ActorIdsignature_); - TRY_STATUS_PREFIX(enc->check_signature(serialize_tl_object(tl, true).as_slice(), sig.as_slice()), - "bad node signature: "); + TRY_STATUS(node.check_signature()); node_ = std::move(node); td::actor::send_closure(adnl, &adnl::Adnl::add_peer, self_id, node_.adnl_id(), node_.addr_list()); @@ -75,13 +67,13 @@ void DhtRemoteNode::send_ping(bool client_only, td::actor::ActorId a td::actor::send_closure(adnl, &adnl::Adnl::add_peer, src, node_.adnl_id(), node_.addr_list()); - auto P = td::PromiseCreator::lambda([key = id_, id = node_.adnl_id().compute_short_id(), client_only, node, src, - adnl](td::Result R) mutable { + auto P = td::PromiseCreator::lambda([key = id_, id = node_.adnl_id().compute_short_id(), client_only, node, src, adnl, + our_network_id = our_network_id_](td::Result R) mutable { if (R.is_error()) { LOG(ERROR) << "[dht]: failed to get self node"; return; } - auto P = td::PromiseCreator::lambda([key, node, adnl](td::Result R) { + auto P = td::PromiseCreator::lambda([key, node, adnl, our_network_id](td::Result R) { if (R.is_error()) { VLOG(DHT_INFO) << "[dht]: received error for query to " << key << ": " << R.move_as_error(); return; @@ -89,7 +81,7 @@ void DhtRemoteNode::send_ping(bool client_only, td::actor::ActorId a auto F = fetch_tl_object(R.move_as_ok(), true); if (F.is_ok()) { - auto N = DhtNode::create(F.move_as_ok()); + auto N = DhtNode::create(F.move_as_ok(), our_network_id); if (N.is_ok()) { td::actor::send_closure(node, &DhtMember::receive_ping, key, N.move_as_ok()); } else { @@ -123,7 +115,8 @@ adnl::AdnlNodeIdFull DhtRemoteNode::get_full_id() const { return node_.adnl_id(); } -td::Result> DhtRemoteNode::create(DhtNode node, td::uint32 max_missed_pings) { +td::Result> DhtRemoteNode::create(DhtNode node, td::uint32 max_missed_pings, + td::int32 our_network_id) { TRY_RESULT(enc, node.adnl_id().pubkey().create_encryptor()); auto tl = node.tl(); auto sig = std::move(tl->signature_); @@ -131,7 +124,7 @@ td::Result> DhtRemoteNode::create(DhtNode node, t TRY_STATUS_PREFIX(enc->check_signature(serialize_tl_object(tl, true).as_slice(), sig.as_slice()), "bad node signature: "); - return std::make_unique(std::move(node), max_missed_pings); + return std::make_unique(std::move(node), max_missed_pings, our_network_id); } } // namespace dht diff --git a/dht/dht-remote-node.hpp b/dht/dht-remote-node.hpp index e65c0429..f0a67e32 100644 --- a/dht/dht-remote-node.hpp +++ b/dht/dht-remote-node.hpp @@ -40,6 +40,7 @@ class DhtRemoteNode { DhtNode node_; td::uint32 max_missed_pings_; + td::int32 our_network_id_; td::uint32 missed_pings_ = 0; double last_ping_at_ = 0; double ready_from_ = 0; @@ -47,12 +48,13 @@ class DhtRemoteNode { td::int32 version_; public: - DhtRemoteNode(DhtNode node, td::uint32 max_missed_pings) - : node_(std::move(node)), max_missed_pings_(max_missed_pings) { + DhtRemoteNode(DhtNode node, td::uint32 max_missed_pings, td::int32 our_network_id) + : node_(std::move(node)), max_missed_pings_(max_missed_pings), our_network_id_(our_network_id) { failed_from_ = td::Time::now_cached(); id_ = node_.get_key(); } - static td::Result> create(DhtNode node, td::uint32 max_missed_pings); + static td::Result> create(DhtNode node, td::uint32 max_missed_pings, + td::int32 our_network_id); DhtNode get_node() const { return node_.clone(); } diff --git a/dht/dht.cpp b/dht/dht.cpp index e5a310e9..a6367a35 100644 --- a/dht/dht.cpp +++ b/dht/dht.cpp @@ -20,7 +20,6 @@ #include "td/utils/tl_storers.h" #include "td/utils/crypto.h" -#include "td/utils/tl_parsers.h" #include "td/utils/Random.h" #include "td/utils/base64.h" @@ -28,9 +27,6 @@ #include "td/db/RocksDb.h" -#include "keys/encryptor.h" -#include "adnl/utils.hpp" - #include "auto/tl/ton_api.hpp" #include "dht.h" @@ -44,10 +40,9 @@ namespace dht { td::actor::ActorOwn DhtMember::create(adnl::AdnlNodeIdShort id, std::string db_root, td::actor::ActorId keyring, - td::actor::ActorId adnl, td::uint32 k, td::uint32 a, - bool client_only) { - return td::actor::ActorOwn( - td::actor::create_actor("dht", id, db_root, keyring, adnl, k, a, client_only)); + td::actor::ActorId adnl, td::int32 network_id, + td::uint32 k, td::uint32 a, bool client_only) { + return td::actor::create_actor("dht", id, db_root, keyring, adnl, network_id, k, a, client_only); } td::Result> Dht::create(adnl::AdnlNodeIdShort id, std::string db_root, @@ -57,7 +52,7 @@ td::Result> Dht::create(adnl::AdnlNodeIdShort id, std:: CHECK(conf->get_k() > 0); CHECK(conf->get_a() > 0); - auto D = DhtMember::create(id, db_root, keyring, adnl, conf->get_k(), conf->get_a()); + auto D = DhtMember::create(id, db_root, keyring, adnl, conf->get_network_id(), conf->get_k(), conf->get_a()); auto &nodes = conf->nodes(); for (auto &node : nodes.list()) { @@ -74,7 +69,7 @@ td::Result> Dht::create_client(adnl::AdnlNodeIdShort id CHECK(conf->get_k() > 0); CHECK(conf->get_a() > 0); - auto D = DhtMember::create(id, db_root, keyring, adnl, conf->get_k(), conf->get_a(), true); + auto D = DhtMember::create(id, db_root, keyring, adnl, conf->get_network_id(), conf->get_k(), conf->get_a(), true); auto &nodes = conf->nodes(); for (auto &node : nodes.list()) { @@ -115,12 +110,12 @@ void DhtMemberImpl::start_up() { V.ensure(); auto nodes = std::move(V.move_as_ok()->nodes_); auto s = nodes->nodes_.size(); - DhtNodesList list{std::move(nodes)}; + DhtNodesList list{std::move(nodes), network_id_}; CHECK(list.size() == s); auto &B = buckets_[bit]; for (auto &node : list.list()) { auto key = node.get_key(); - B.add_full_node(key, std::move(node), adnl_, id_); + B.add_full_node(key, std::move(node), adnl_, id_, network_id_); } } } @@ -368,7 +363,7 @@ void DhtMemberImpl::receive_query(adnl::AdnlNodeIdShort src, td::BufferSlice dat { auto R = fetch_tl_prefix(data, true); if (R.is_ok()) { - auto N = DhtNode::create(std::move(R.move_as_ok()->node_)); + auto N = DhtNode::create(std::move(R.move_as_ok()->node_), network_id_); if (N.is_ok()) { auto node = N.move_as_ok(); auto key = node.get_key(); @@ -396,7 +391,7 @@ void DhtMemberImpl::receive_query(adnl::AdnlNodeIdShort src, td::BufferSlice dat VLOG(DHT_EXTRA_DEBUG) << this << ": query to DHT from " << src << ": " << ton_api::to_string(Q); - ton_api::downcast_call(*Q.get(), [&](auto &object) { this->process_query(src, object, std::move(promise)); }); + ton_api::downcast_call(*Q, [&](auto &object) { this->process_query(src, object, std::move(promise)); }); } void DhtMemberImpl::add_full_node(DhtKeyId key, DhtNode node) { @@ -411,7 +406,7 @@ void DhtMemberImpl::add_full_node(DhtKeyId key, DhtNode node) { #endif if (bit < 256) { CHECK(key.get_bit(bit) != key_.get_bit(bit)); - buckets_[bit].add_full_node(key, std::move(node), adnl_, id_); + buckets_[bit].add_full_node(key, std::move(node), adnl_, id_, network_id_); } else { CHECK(key == key_); } @@ -467,10 +462,11 @@ void DhtMemberImpl::set_value(DhtValue value, td::Promise promise) { void DhtMemberImpl::get_value_in(DhtKeyId key, td::Promise result) { auto P = td::PromiseCreator::lambda([key, promise = std::move(result), SelfId = actor_id(this), print_id = print_id(), - adnl = adnl_, list = get_nearest_nodes(key, k_), k = k_, a = a_, id = id_, + adnl = adnl_, list = get_nearest_nodes(key, k_), k = k_, a = a_, + network_id = network_id_, id = id_, client_only = client_only_](td::Result R) mutable { R.ensure(); - td::actor::create_actor("FindValueQuery", key, print_id, id, std::move(list), k, a, + td::actor::create_actor("FindValueQuery", key, print_id, id, std::move(list), k, a, network_id, R.move_as_ok(), client_only, SelfId, adnl, std::move(promise)) .release(); }); @@ -495,7 +491,7 @@ void DhtMemberImpl::register_reverse_connection(adnl::AdnlNodeIdFull client, td: td::actor::create_actor( "RegisterReverseQuery", key_id, std::move(client), ttl, std::move(signature), print_id, id_, std::move(list), k_, a_, - R.move_as_ok(), client_only_, SelfId, adnl_, + network_id_, R.move_as_ok(), client_only_, SelfId, adnl_, std::move(promise)) .release(); }); @@ -535,9 +531,9 @@ void DhtMemberImpl::request_reverse_ping_cont(adnl::AdnlNode target, td::BufferS SelfId = actor_id(this), print_id = print_id(), list = get_nearest_nodes(key_id, k_), client_only = client_only_](td::Result R) mutable { R.ensure(); - td::actor::create_actor("RequestReversePing", client, std::move(target), - std::move(signature), print_id, id_, std::move(list), k_, a_, - R.move_as_ok(), client_only, SelfId, adnl_, std::move(promise)) + td::actor::create_actor( + "RequestReversePing", client, std::move(target), std::move(signature), print_id, id_, std::move(list), k_, a_, + network_id_, R.move_as_ok(), client_only, SelfId, adnl_, std::move(promise)) .release(); }); } @@ -652,9 +648,10 @@ void DhtMemberImpl::check() { DhtKeyId key{x}; auto P = td::PromiseCreator::lambda([key, promise = std::move(promise), SelfId = actor_id(this), print_id = print_id(), adnl = adnl_, list = get_nearest_nodes(key, k_), k = k_, - a = a_, id = id_, client_only = client_only_](td::Result R) mutable { + a = a_, network_id = network_id_, id = id_, + client_only = client_only_](td::Result R) mutable { R.ensure(); - td::actor::create_actor("FindNodesQuery", key, print_id, id, std::move(list), k, a, + td::actor::create_actor("FindNodesQuery", key, print_id, id, std::move(list), k, a, network_id, R.move_as_ok(), client_only, SelfId, adnl, std::move(promise)) .release(); }); @@ -675,63 +672,71 @@ void DhtMemberImpl::send_store(DhtValue value, td::Promise promise) { value.check().ensure(); auto key_id = value.key_id(); - auto P = - td::PromiseCreator::lambda([value = std::move(value), print_id = print_id(), id = id_, client_only = client_only_, - list = get_nearest_nodes(key_id, k_), k = k_, a = a_, SelfId = actor_id(this), - adnl = adnl_, promise = std::move(promise)](td::Result R) mutable { - R.ensure(); - td::actor::create_actor("StoreQuery", std::move(value), print_id, id, std::move(list), k, a, - R.move_as_ok(), client_only, SelfId, adnl, std::move(promise)) - .release(); - }); + auto P = td::PromiseCreator::lambda([value = std::move(value), print_id = print_id(), id = id_, + client_only = client_only_, list = get_nearest_nodes(key_id, k_), k = k_, a = a_, + network_id = network_id_, SelfId = actor_id(this), adnl = adnl_, + promise = std::move(promise)](td::Result R) mutable { + R.ensure(); + td::actor::create_actor("StoreQuery", std::move(value), print_id, id, std::move(list), k, a, + network_id, R.move_as_ok(), client_only, SelfId, adnl, std::move(promise)) + .release(); + }); get_self_node(std::move(P)); } void DhtMemberImpl::get_self_node(td::Promise promise) { - auto P = - td::PromiseCreator::lambda([promise = std::move(promise), print_id = print_id(), id = id_, keyring = keyring_, - client_only = client_only_](td::Result R) mutable { - R.ensure(); - auto node = R.move_as_ok(); - auto version = static_cast(td::Clocks::system()); - auto B = create_serialize_tl_object(node.pub_id().tl(), node.addr_list().tl(), version, - td::BufferSlice()); - if (!client_only) { - CHECK(node.addr_list().size() > 0); - } - auto P = td::PromiseCreator::lambda( - [promise = std::move(promise), node = std::move(node), version](td::Result R) mutable { - R.ensure(); - DhtNode n{node.pub_id(), node.addr_list(), version, R.move_as_ok()}; - promise.set_result(std::move(n)); - }); - td::actor::send_closure(keyring, &keyring::Keyring::sign_message, id.pubkey_hash(), std::move(B), std::move(P)); - }); + auto P = td::PromiseCreator::lambda([promise = std::move(promise), print_id = print_id(), id = id_, + keyring = keyring_, client_only = client_only_, + network_id = network_id_](td::Result R) mutable { + R.ensure(); + auto node = R.move_as_ok(); + auto version = static_cast(td::Clocks::system()); + td::BufferSlice B = serialize_tl_object( + DhtNode{node.pub_id(), node.addr_list(), version, network_id, td::BufferSlice{}}.tl(), true); + if (!client_only) { + CHECK(node.addr_list().size() > 0); + } + auto P = td::PromiseCreator::lambda([promise = std::move(promise), node = std::move(node), version, + network_id](td::Result R) mutable { + R.ensure(); + DhtNode n{node.pub_id(), node.addr_list(), version, network_id, R.move_as_ok()}; + promise.set_result(std::move(n)); + }); + td::actor::send_closure(keyring, &keyring::Keyring::sign_message, id.pubkey_hash(), std::move(B), std::move(P)); + }); td::actor::send_closure(adnl_, &adnl::Adnl::get_self_node, id_, std::move(P)); } -td::Result> Dht::create_global_config(tl_object_ptr conf) { - td::uint32 k; - if (conf->k_ == 0) { +td::Result> Dht::create_global_config(tl_object_ptr conf) { + td::uint32 k = 0, a = 0; + td::int32 network_id = -1; + tl_object_ptr static_nodes; + ton_api::downcast_call(*conf, td::overloaded( + [&](ton_api::dht_config_global &f) { + k = f.k_; + a = f.a_; + network_id = -1; + static_nodes = std::move(f.static_nodes_); + }, + [&](ton_api::dht_config_global_v2 &f) { + k = f.k_; + a = f.a_; + network_id = f.network_id_; + static_nodes = std::move(f.static_nodes_); + })); + if (k == 0) { k = DhtMember::default_k(); - } else if (conf->k_ > 0 && static_cast(conf->k_) <= DhtMember::max_k()) { - k = conf->k_; - } else { - return td::Status::Error(ErrorCode::protoviolation, PSTRING() << "bad value k=" << conf->k_); + } else if (k > DhtMember::max_k()) { + return td::Status::Error(ErrorCode::protoviolation, PSTRING() << "bad value k=" << k); } - td::uint32 a; - if (conf->a_ == 0) { + if (a == 0) { a = DhtMember::default_a(); - } else if (conf->a_ > 0 && static_cast(conf->a_) <= DhtMember::max_a()) { - a = conf->a_; - } else { - return td::Status::Error(ErrorCode::protoviolation, PSTRING() << "bad value a=" << conf->a_); + } else if (a > DhtMember::max_a()) { + return td::Status::Error(ErrorCode::protoviolation, PSTRING() << "bad value a=" << a); } - - DhtNodesList l{std::move(conf->static_nodes_)}; - - return std::make_shared(k, a, std::move(l)); + DhtNodesList l{std::move(static_nodes), network_id}; + return std::make_shared(k, a, network_id, std::move(l)); } } // namespace dht diff --git a/dht/dht.h b/dht/dht.h index d4c5edf7..b9c65c8a 100644 --- a/dht/dht.h +++ b/dht/dht.h @@ -47,7 +47,7 @@ class Dht : public td::actor::Actor { td::actor::ActorId keyring, td::actor::ActorId adnl); static td::Result> create_global_config( - tl_object_ptr conf); + tl_object_ptr conf); virtual adnl::AdnlNodeIdShort get_id() const = 0; diff --git a/dht/dht.hpp b/dht/dht.hpp index 5a4c4cfb..0b46d635 100644 --- a/dht/dht.hpp +++ b/dht/dht.hpp @@ -52,15 +52,20 @@ class DhtGlobalConfig { auto get_a() const { return a_; } + auto get_network_id() const { + return network_id_; + } const auto &nodes() const { return static_nodes_; } - DhtGlobalConfig(td::uint32 k, td::uint32 a, DhtNodesList nodes) : k_(k), a_(a), static_nodes_(std::move(nodes)) { + DhtGlobalConfig(td::uint32 k, td::uint32 a, td::int32 network_id, DhtNodesList nodes) + : k_(k), a_(a), network_id_(network_id), static_nodes_(std::move(nodes)) { } private: td::uint32 k_; td::uint32 a_; + td::int32 network_id_; DhtNodesList static_nodes_; }; @@ -85,8 +90,8 @@ class DhtMember : public Dht { static td::actor::ActorOwn create(adnl::AdnlNodeIdShort id, std::string db_root, td::actor::ActorId keyring, - td::actor::ActorId adnl, td::uint32 k = 10, td::uint32 a = 3, - bool client_only = false); + td::actor::ActorId adnl, td::int32 network_id, + td::uint32 k = 10, td::uint32 a = 3, bool client_only = false); //virtual void update_addr_list(tl_object_ptr addr_list) = 0; //virtual void add_node(adnl::AdnlNodeIdShort id) = 0; diff --git a/dht/utils/dht-resolve.cpp b/dht/utils/dht-resolve.cpp index f30d8fa7..5ab98d01 100644 --- a/dht/utils/dht-resolve.cpp +++ b/dht/utils/dht-resolve.cpp @@ -132,7 +132,9 @@ class Resolver : public td::actor::Actor { if (!conf.dht_) { return td::Status::Error(ton::ErrorCode::error, "does not contain [dht] section"); } - auto &nodes = conf.dht_->static_nodes_->nodes_; + ton::ton_api::dht_nodes* static_nodes = nullptr; + ton::ton_api::downcast_call(*conf.dht_, [&](auto &f) { static_nodes = f.static_nodes_.get(); }); + auto &nodes = static_nodes->nodes_; if (server_idx_ >= 0) { CHECK(server_idx_ < (int)nodes.size()); LOG(INFO) << "Using server #" << server_idx_; diff --git a/tl/generate/scheme/ton_api.tl b/tl/generate/scheme/ton_api.tl index 524d2592..8b5a49f7 100644 --- a/tl/generate/scheme/ton_api.tl +++ b/tl/generate/scheme/ton_api.tl @@ -562,11 +562,12 @@ control.config.local priv:PrivateKey pub:int256 port:int = control.config.Local; config.local local_ids:(vector id.config.local) dht:(vector dht.config.Local) validators:(vector validator.config.Local) liteservers:(vector liteserver.config.Local) control:(vector control.config.local) = config.Local; dht.config.global static_nodes:dht.nodes k:int a:int = dht.config.Global; +dht.config.global_v2 static_nodes:dht.nodes k:int a:int network_id:int = dht.config.Global; adnl.config.global static_nodes:adnl.nodes = adnl.config.Global; catchain.config.global tag:int256 nodes:(vector PublicKey) = catchain.config.Global; dummyworkchain0.config.global zero_state_hash:int256 = dummyworkchain0.config.Global; validator.config.global zero_state:tonNode.blockIdExt init_block:tonNode.blockIdExt hardforks:(vector tonNode.blockIdExt) = validator.config.Global; -config.global adnl:adnl.config.global dht:dht.config.global validator:validator.config.global = config.Global; +config.global adnl:adnl.config.global dht:dht.config.Global validator:validator.config.global = config.Global; liteserver.desc id:PublicKey ip:int port:int = liteserver.Desc; liteclient.config.global liteservers:(vector liteserver.desc) validator:validator.config.global = liteclient.config.Global; diff --git a/tl/generate/scheme/ton_api.tlo b/tl/generate/scheme/ton_api.tlo index 0eb060b0..b9350346 100644 Binary files a/tl/generate/scheme/ton_api.tlo and b/tl/generate/scheme/ton_api.tlo differ