├── include ├── random_layered_broadcast.h ├── gossip_set_layer.h ├── header_block_data.h ├── gossip_bloomfilter_layer.h ├── gossip_bloomfilter.h ├── gossip_filter.h ├── gossip_utils.h ├── mesages_with_bloomfilter.h ├── broadcast_layered.h └── block_sync_manager.h ├── CMakeLists.txt ├── tests ├── CMakeLists.txt ├── test_main.cc ├── test_gossip_bloomfilter_layer.cc ├── test_broadcast_layered.cc ├── test_ips.h └── test_gossip_interface.cc ├── xgossip.xcodeproj ├── xcuserdata │ └── imac.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── project.pbxproj ├── src ├── gossip_utils.cc ├── header_block_data.cc ├── messages_with_bloomfilter.cc ├── gossip_set_layer.cc ├── gossip_bloomfilter.cc ├── gossip_filter.cc ├── gossip_bloomfilter_layer.cc ├── broadcast_layered.cc ├── block_sync_manager.cc └── gossip_interface.cc ├── README.md └── gossip_interface.h /include/random_layered_broadcast.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | 3 | aux_source_directory(./src xgossip_src) 4 | add_library(xgossip STATIC ${xgossip_src}) 5 | 6 | add_dependencies(xgossip xkad) 7 | target_link_libraries(xgossip PRIVATE xkad xpbase xtransport xwrouter cpp_redis tacopie) 8 | 9 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux") 10 | if (XENABLE_CODE_COVERAGE) 11 | target_link_libraries(xgossip PRIVATE gcov) 12 | endif() 13 | endif() 14 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | aux_source_directory(./ xgossip_test_dir) 2 | 3 | add_executable(xgossip_test ${xgossip_test_dir}) 4 | 5 | add_dependencies(xgossip_test xgossip xxbase) 6 | 7 | target_link_libraries(xgossip_test 8 | xgossip 9 | xkad 10 | xtransport 11 | xpbase 12 | xledger 13 | xcrypto 14 | xutility 15 | xxbase 16 | common 17 | protobuf 18 | -lgtest 19 | -lgmock 20 | -lpthread -ldl 21 | -lrt 22 | ) 23 | 24 | -------------------------------------------------------------------------------- /xgossip.xcodeproj/xcuserdata/imac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | xgossip.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 4 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /include/gossip_set_layer.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include "xtransport/transport.h" 8 | #include "xgossip/gossip_interface.h" 9 | 10 | namespace top { 11 | 12 | namespace gossip { 13 | 14 | class GossipSetLayer : public GossipInterface { 15 | public: 16 | explicit GossipSetLayer(transport::TransportPtr transport_ptr); 17 | virtual ~GossipSetLayer(); 18 | virtual void Broadcast( 19 | uint64_t local_hash64, 20 | transport::protobuf::RoutingMessage& message, 21 | std::shared_ptr> neighbors); 22 | 23 | private: 24 | 25 | DISALLOW_COPY_AND_ASSIGN(GossipSetLayer); 26 | }; 27 | 28 | } // namespace gossip 29 | 30 | } // namespace top 31 | -------------------------------------------------------------------------------- /include/header_block_data.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include "xledger/xledger_face.h" 8 | #include "xpbase/base/top_utils.h" 9 | 10 | namespace top { 11 | 12 | namespace gossip { 13 | 14 | class HeaderBlockData { 15 | public: 16 | explicit HeaderBlockData(std::shared_ptr ledger_face); 17 | ~HeaderBlockData(); 18 | void AddData(const std::string& header_hash, const std::string& block); 19 | void GetData(const std::string& header_hash, std::string& block); 20 | bool HasData(const std::string& header_hash); 21 | void RemoveData(const std::string& header_hash); 22 | 23 | private: 24 | std::shared_ptr ledger_face_; 25 | 26 | DISALLOW_COPY_AND_ASSIGN(HeaderBlockData); 27 | }; 28 | 29 | } // namespace gossip 30 | 31 | } // namespace top 32 | -------------------------------------------------------------------------------- /src/gossip_utils.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xgossip/include/gossip_utils.h" 6 | 7 | namespace top { 8 | 9 | namespace gossip { 10 | 11 | static const uint32_t kReliableHighNeighbersCount = 8u; 12 | static const uint32_t kReliableMiddleNeighbersCount = 5u; 13 | static const uint32_t kReliableLowNeighbersCount = 3u; 14 | 15 | uint32_t GetRandomNeighbersCount(uint32_t reliable_level) { 16 | switch (reliable_level) { 17 | case kGossipReliableInvalid: 18 | return kReliableHighNeighbersCount; 19 | case kGossipReliableHigh: 20 | return kReliableHighNeighbersCount; 21 | case kGossipReliableMiddle: 22 | return kReliableMiddleNeighbersCount; 23 | case kGossipReliableLow: 24 | return kReliableLowNeighbersCount; 25 | default: 26 | return kReliableLowNeighbersCount; 27 | } 28 | } 29 | 30 | } // namespace gossip 31 | 32 | } // namespace top 33 | -------------------------------------------------------------------------------- /include/gossip_bloomfilter_layer.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include "xtransport/transport.h" 8 | #include "xgossip/gossip_interface.h" 9 | 10 | namespace top { 11 | 12 | namespace gossip { 13 | 14 | class GossipBloomfilterLayer : public GossipInterface { 15 | public: 16 | explicit GossipBloomfilterLayer(transport::TransportPtr transport_ptr); 17 | virtual ~GossipBloomfilterLayer(); 18 | virtual void Broadcast( 19 | uint64_t local_hash64, 20 | transport::protobuf::RoutingMessage& message, 21 | std::shared_ptr> neighbors); 22 | virtual void Broadcast( 23 | transport::protobuf::RoutingMessage& message, 24 | kadmlia::RoutingTablePtr& routing_table); 25 | 26 | private: 27 | 28 | DISALLOW_COPY_AND_ASSIGN(GossipBloomfilterLayer); 29 | }; 30 | 31 | } // namespace gossip 32 | 33 | } // namespace top 34 | -------------------------------------------------------------------------------- /tests/test_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | #include 7 | 8 | #include "xpbase/base/top_log.h" 9 | #include "xpbase/base/top_config.h" 10 | #include "xkad/routing_table/routing_utils.h" 11 | 12 | namespace top { 13 | std::shared_ptr global_xid; 14 | uint32_t gloabl_platform_type = kPlatform; 15 | std::string global_node_id = RandomString(256); 16 | std::string global_node_id_hash(""); 17 | } 18 | 19 | int main(int argc, char *argv[]) { 20 | xinit_log("bitvpn_ut.log", true, true); 21 | xset_log_level(enum_xlog_level_debug); 22 | top::base::Config config; 23 | config.Init("./conf.ut/test_routing_table.conf"); 24 | top::kadmlia::CreateGlobalXid(config); 25 | 26 | testing::GTEST_FLAG(output) = "xml:"; 27 | testing::InitGoogleTest(&argc, argv); 28 | ::testing::InitGoogleMock(&argc, argv); 29 | int ret = RUN_ALL_TESTS(); 30 | TOP_INFO("exit"); 31 | return ret; 32 | } 33 | -------------------------------------------------------------------------------- /include/gossip_bloomfilter.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include "xtransport/transport.h" 8 | #include "xgossip/gossip_interface.h" 9 | 10 | namespace top { 11 | 12 | namespace gossip { 13 | 14 | class GossipBloomfilter : public GossipInterface { 15 | public: 16 | explicit GossipBloomfilter(transport::TransportPtr transport_ptr); 17 | virtual ~GossipBloomfilter(); 18 | virtual void Broadcast( 19 | uint64_t local_hash64, 20 | transport::protobuf::RoutingMessage& message, 21 | std::shared_ptr> neighbors); 22 | 23 | // just for performance test 24 | virtual void BroadcastWithNoFilter( 25 | const std::string& local_id, 26 | transport::protobuf::RoutingMessage& message, 27 | const std::vector& neighbors); 28 | 29 | private: 30 | 31 | DISALLOW_COPY_AND_ASSIGN(GossipBloomfilter); 32 | }; 33 | 34 | } // namespace gossip 35 | 36 | } // namespace top 37 | -------------------------------------------------------------------------------- /include/gossip_filter.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "xtransport/proto/transport.pb.h" 12 | 13 | namespace top { 14 | 15 | namespace base { 16 | class TimerRepeated; 17 | } 18 | 19 | namespace gossip { 20 | 21 | static const uint32_t kRepeatedValue = 1; 22 | static const uint64_t kClearRstPeriod = 15ll * 1000ll * 1000ll; // 5 seconds 23 | typedef std::shared_ptr> HashMapPtr; 24 | 25 | class GossipFilter { 26 | public: 27 | static GossipFilter* Instance(); 28 | 29 | bool Init(); 30 | bool FilterMessage(transport::protobuf::RoutingMessage& message); 31 | 32 | protected: 33 | bool AddData(uint32_t); 34 | bool FindData(uint32_t); 35 | void do_clear_and_reset(); 36 | void AddRepeatMsg(uint32_t key); 37 | void PrintRepeatMap(); 38 | 39 | private: 40 | GossipFilter(); 41 | ~GossipFilter(); 42 | 43 | private: 44 | bool inited_{false}; 45 | std::vector time_filter_; 46 | std::mutex current_index_mutex_; 47 | uint32_t current_index_; 48 | std::shared_ptr timer_{nullptr}; 49 | std::mutex repeat_map_mutex_; 50 | std::map repeat_map_; 51 | std::shared_ptr remap_timer_{nullptr}; 52 | }; 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /include/gossip_utils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include "xkad/routing_table/routing_utils.h" 11 | 12 | namespace top { 13 | 14 | namespace gossip { 15 | 16 | enum ReliableLevel { 17 | kGossipReliableInvalid = 0, 18 | kGossipReliableHigh = 1, 19 | kGossipReliableMiddle = 2, 20 | kGossipReliableLow = 3, 21 | }; 22 | 23 | enum GossipType { 24 | kGossipInvalid = 0, 25 | kGossipBloomfilter = 1, 26 | kGossipLayeredBroadcast = 2, 27 | kGossipBloomfilterAndLayered = 3, 28 | kGossipSetFilterAndLayered = 4, 29 | }; 30 | 31 | /* 32 | enum GossipBlockSyncType { 33 | kGossipBlockSyncInvalid = kadmlia::kKadMessageTypeMax + 1, 34 | kGossipBlockSyncAsk, 35 | kGossipBlockSyncAck, 36 | kGossipBlockSyncRequest, 37 | kGossipBlockSyncResponse, 38 | 39 | kGossipMaxMessageType, 40 | }; 41 | */ 42 | 43 | static const uint32_t kGossipSendoutMaxTimes = 3u; 44 | static const uint32_t kGossipSendoutMaxNeighbors = 3u; 45 | static const uint32_t kGossipSwitchLayerCount = 2u; 46 | static const uint32_t kGossipBloomfilterSize = 256u; 47 | static const uint32_t kGossipBloomfilterHashNum = 3u; 48 | static const uint32_t kGossipBloomfilterIgnoreLevel = 1u; 49 | 50 | uint32_t GetRandomNeighbersCount(uint32_t reliable_level); 51 | 52 | } // namespace gossip 53 | 54 | } // namespace top 55 | -------------------------------------------------------------------------------- /include/mesages_with_bloomfilter.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "xpbase/base/uint64_bloomfilter.h" 12 | #include "xpbase/base/top_timer.h" 13 | #include "xtransport/proto/transport.pb.h" 14 | 15 | namespace top { 16 | 17 | namespace gossip { 18 | 19 | struct GossipItem { 20 | std::shared_ptr bloom_filter; 21 | uint32_t sendout_times; 22 | }; 23 | 24 | class MessageWithBloomfilter { 25 | public: 26 | static MessageWithBloomfilter* Instance(); 27 | std::shared_ptr GetMessageBloomfilter( 28 | transport::protobuf::RoutingMessage& message, 29 | bool& stop_gossip); 30 | bool StopGossip(const uint32_t&, uint32_t); 31 | 32 | private: 33 | MessageWithBloomfilter() {} 34 | ~MessageWithBloomfilter() {} 35 | 36 | std::shared_ptr MergeBloomfilter( 37 | const uint32_t&, 38 | std::shared_ptr& bloomfilter, 39 | const uint32_t& stop_times, 40 | bool& stop_gossip); 41 | 42 | // static const uint32_t kMaxMessageQueueSize = 1048576u; 43 | static const uint32_t kMaxMessageQueueSize = 508576u; 44 | 45 | std::unordered_map messsage_bloomfilter_map_; 46 | std::mutex messsage_bloomfilter_map_mutex_; 47 | 48 | DISALLOW_COPY_AND_ASSIGN(MessageWithBloomfilter); 49 | }; 50 | 51 | } // namespace gossip 52 | 53 | } // namespace top 54 | -------------------------------------------------------------------------------- /src/header_block_data.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xgossip/include/header_block_data.h" 6 | 7 | #include "xdata/xdataobject.h" 8 | 9 | namespace top { 10 | 11 | namespace gossip { 12 | 13 | HeaderBlockData::HeaderBlockData(std::shared_ptr ledger_face) 14 | : ledger_face_(ledger_face) {} 15 | 16 | HeaderBlockData::~HeaderBlockData() {} 17 | 18 | void HeaderBlockData::AddData(const std::string& header_hash, const std::string& block) { 19 | assert(ledger_face_); 20 | xdataobject_string_ptr_t str_obj = make_object_ptr(); 21 | str_obj->set(block); 22 | ledger_face_->set( 23 | header_hash, 24 | str_obj, 25 | 0, 26 | 0, 27 | top::ledger::enum_xledger_set_obj_expire_flag); 28 | } 29 | 30 | void HeaderBlockData::GetData(const std::string& header_hash, std::string& block) { 31 | assert(ledger_face_); 32 | xdataobject_string_ptr_t str_obj = ledger_face_->get(header_hash); 33 | if (str_obj == nullptr) { 34 | return; 35 | } 36 | block = str_obj->get(); 37 | } 38 | 39 | bool HeaderBlockData::HasData(const std::string& header_hash) { 40 | assert(ledger_face_); 41 | xdataobject_string_ptr_t str_obj = ledger_face_->get(header_hash); 42 | if (str_obj == nullptr) { 43 | return false; 44 | } 45 | return true; 46 | } 47 | 48 | void HeaderBlockData::RemoveData(const std::string& header_hash) { 49 | assert(ledger_face_); 50 | ledger_face_->remove(header_hash); 51 | } 52 | 53 | } // namespace gossip 54 | 55 | } // namespace top 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xgossip 2 | 3 | A High Performance Gossip Protocol implementation of TOP Network. 4 | 5 | ## Feature highlights 6 | 7 | + Fully designed for Multi-Cores and Muti-Threads 8 | + High Performance & Low memory/cpu consumption 9 | + a lot of innovations on the basis of the original gossip 10 | + Unique in the industry 11 | + Bloom filter to De-weighting 12 | + Anti-dropping & high efficiency transport 13 | + iOS, Android, Windows, MacOS, Linux support 14 | 15 | ## Algorithm Description 16 | 17 | ### gossip based bloomfilter 18 | 19 | This kind of broadcasting algorithm is more like traditional gossip broadcast, but we delete duplications in the process of broadcasting by bloomfilter to avoid Netstorm and achieve more effective broadcast on condition of limited bandwidth. According to practical testing data, the broadcast can be done when the number of receiving packets of node cluster is 5~9 times the sum of nodes. 20 | 21 | ### gossip based multi-layer & sorted select 22 | 23 | The packet loss resistance of the above algorithm is good, but its redundancy is too high. For the network that has limited number of nodes, it can achieve mutually exclusive selection of nodes in the broadcasting process and reduce sharply bandwidth redundancy. According to practical testing data, the broadcast can be done when the number of receiving packets of node cluster is same as the sum of nodes. 24 | 25 | ### gossip based multi-layer & sorted select & bloomfilter 26 | 27 | The above-mentioned algorithm can both exert respective advantages in certain scenarios. This kind of broadcasting algorithm is achieved by combining algorithm 1 and algorithm 3. Synergistic selection based on bloomfilter and node ID hash can support mutual exclusivity and realize high-performance broadcast. According to practical testing data, the broadcast can be done when the number of receiving packets of node cluster is 1-2 times the sum of nodes. 28 | 29 | ## Example 30 | 31 | ### C++ example 32 | 33 | simple Examples in tests directory 34 | 35 | ## Contact 36 | 37 | [TOP Network](https://www.topnetwork.org/) 38 | 39 | ## License 40 | 41 | Copyright (c) 2017-2019 Telos Foundation & contributors 42 | 43 | Distributed under the MIT software license, see the accompanying 44 | 45 | file COPYING or http://www.opensource.org/licenses/mit-license.php. 46 | -------------------------------------------------------------------------------- /include/broadcast_layered.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #include "xtransport/transport.h" 10 | #include "xkad/routing_table/node_info.h" 11 | #include "xgossip/gossip_interface.h" 12 | 13 | namespace top { 14 | 15 | namespace kadmlia { 16 | class RoutingTable; 17 | typedef std::shared_ptr RoutingTablePtr; 18 | }; 19 | 20 | namespace gossip { 21 | 22 | class BroadcastLayered : public GossipInterface { 23 | public: 24 | explicit BroadcastLayered(transport::TransportPtr transport_ptr); 25 | virtual ~BroadcastLayered(); 26 | virtual void Broadcast( 27 | uint64_t local_hash64, 28 | transport::protobuf::RoutingMessage& message, 29 | std::shared_ptr> neighbors) { return; } 30 | 31 | virtual void Broadcast( 32 | transport::protobuf::RoutingMessage& message, 33 | kadmlia::RoutingTablePtr& routing_table); 34 | 35 | private: 36 | void GetNextBroadcastNodes( 37 | transport::protobuf::RoutingMessage& message, 38 | kadmlia::RoutingTablePtr& routing_table, 39 | std::vector& broadcast_nodes); 40 | int32_t FindSelfSortIndex( 41 | transport::protobuf::RoutingMessage& message, 42 | kadmlia::RoutingTablePtr& routing_table); 43 | std::vector choose_nodes( 44 | int hop_num, 45 | uint32_t self_sort_index, 46 | uint32_t neighber_count, 47 | const std::vector& sort_nodes_index_vec); 48 | uint32_t find_hop_num(uint32_t self_sort_index, uint32_t neighber_count); 49 | std::vector choose_next_nodes( 50 | uint32_t count, 51 | uint32_t self_node_index, 52 | uint32_t neighber_count); 53 | uint32_t FindLogicalSelfIndex( 54 | uint32_t real_self_index, 55 | uint32_t random_step, 56 | uint32_t nodes_size); 57 | uint32_t FindRealSelfIndex( 58 | uint32_t logical_self_index, 59 | uint32_t random_step, 60 | uint32_t nodes_size); 61 | void GetRangeNodes( 62 | kadmlia::RoutingTablePtr& routing_table, 63 | const uint32_t& min_index, 64 | const uint32_t& max_index, 65 | std::vector& vec); 66 | 67 | 68 | }; 69 | 70 | } // namespace gossip 71 | 72 | } // namespace top 73 | -------------------------------------------------------------------------------- /gossip_interface.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | #include "xbase/xpacket.h" 10 | #include "xtransport/proto/transport.pb.h" 11 | #include "xtransport/transport.h" 12 | #include "xkad/routing_table/node_info.h" 13 | #include "xkad/routing_table/routing_table.h" 14 | 15 | namespace top { 16 | 17 | namespace base { 18 | class Uint64BloomFilter; 19 | }; 20 | 21 | namespace gossip { 22 | 23 | class GossipInterface { 24 | public: 25 | virtual void Broadcast( 26 | uint64_t local_hash64, 27 | transport::protobuf::RoutingMessage& message, 28 | std::shared_ptr> neighbors) = 0; 29 | virtual void Broadcast( 30 | transport::protobuf::RoutingMessage& message, 31 | kadmlia::RoutingTablePtr& routing_table) { 32 | return ; 33 | } 34 | 35 | protected: 36 | GossipInterface(transport::TransportPtr transport_ptr) : transport_ptr_(transport_ptr) {} 37 | virtual ~GossipInterface() {} 38 | 39 | uint64_t GetDistance(const std::string& src, const std::string& des); 40 | void Send( 41 | transport::protobuf::RoutingMessage& message, 42 | const std::vector& nodes); 43 | uint32_t GetNeighborCount(transport::protobuf::RoutingMessage& message); 44 | std::vector GetRandomNodes( 45 | std::vector& neighbors, 46 | uint32_t number_to_get) const; 47 | void SelectNodes( 48 | transport::protobuf::RoutingMessage& message, 49 | const std::vector& nodes, 50 | std::vector& select_nodes); 51 | void SelectNodes( 52 | transport::protobuf::RoutingMessage& message, 53 | kadmlia::RoutingTablePtr& routing_table, 54 | std::shared_ptr& bloomfilter, 55 | std::vector& select_nodes); 56 | void SendLayered( 57 | transport::protobuf::RoutingMessage& message, 58 | const std::vector& nodes); 59 | void CheckDiffNetwork(transport::protobuf::RoutingMessage& message); 60 | 61 | // TODO(Charlie): for test evil 62 | bool ThisNodeIsEvil(transport::protobuf::RoutingMessage& message); 63 | bool IsIpValid(const std::string& ip); 64 | 65 | transport::TransportPtr transport_ptr_; 66 | 67 | private: 68 | DISALLOW_COPY_AND_ASSIGN(GossipInterface); 69 | }; 70 | 71 | } // namespace gossip 72 | 73 | } // namespace top 74 | -------------------------------------------------------------------------------- /include/block_sync_manager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "xbase/xpacket.h" 12 | #include "xtransport/proto/transport.pb.h" 13 | #include "xpbase/base/top_timer.h" 14 | #include "xgossip/include/header_block_data.h" 15 | #include "xtransport/message_manager/message_manager_intf.h" 16 | 17 | namespace top { 18 | 19 | namespace kadmlia { 20 | 21 | class RoutingTable; 22 | typedef std::shared_ptr RoutingTablePtr; 23 | 24 | } 25 | 26 | namespace gossip { 27 | 28 | struct SyncBlockItem { 29 | uint64_t routing_service_type; 30 | std::string header_hash; 31 | std::chrono::steady_clock::time_point time_point; 32 | }; 33 | 34 | class BlockSyncManager { 35 | public: 36 | static BlockSyncManager* Instance(); 37 | void SetLeagerFace(std::shared_ptr ledger_face); 38 | void SetRoutingTablePtr(kadmlia::RoutingTablePtr& routing_table); 39 | void NewBroadcastMessage(transport::protobuf::RoutingMessage& message); 40 | 41 | private: 42 | BlockSyncManager(); 43 | ~BlockSyncManager(); 44 | 45 | bool HeaderHashExists(const std::string& header_hash); 46 | uint32_t GetBlockMsgType(const std::string& header_hash); 47 | void AddHeaderHashToQueue( 48 | const std::string& header_hash, 49 | uint64_t service_type); 50 | void CheckHeaderHashQueue(); 51 | uint64_t GetRoutingServiceType(const std::string& des_node_id); 52 | void SendSyncAsk(std::shared_ptr& sync_item); 53 | void HandleSyncAsk( 54 | transport::protobuf::RoutingMessage& message, 55 | base::xpacket_t& packet); 56 | void HandleSyncAck( 57 | transport::protobuf::RoutingMessage& message, 58 | base::xpacket_t& packet); 59 | void HandleSyncRequest( 60 | transport::protobuf::RoutingMessage& message, 61 | base::xpacket_t& packet); 62 | void HandleSyncResponse( 63 | transport::protobuf::RoutingMessage& message, 64 | base::xpacket_t& packet); 65 | bool HeaderRequested(const std::string& header_hash); 66 | void RemoveHeaderBlock(const std::string& header_hash); 67 | bool DataExists(const std::string& header_hash); 68 | 69 | std::map> block_map_; 70 | std::mutex block_map_mutex_; 71 | base::TimerRepeated timer_{base::TimerManager::Instance(), "BlockSyncManager"}; 72 | std::map requested_headers_; 73 | std::mutex requested_headers_mutex_; 74 | std::shared_ptr header_block_data_{ nullptr }; 75 | kadmlia::RoutingTablePtr routing_table_; 76 | transport::MessageManagerIntf* message_manager_{transport::MessageManagerIntf::Instance()}; 77 | 78 | DISALLOW_COPY_AND_ASSIGN(BlockSyncManager); 79 | }; 80 | 81 | } // namespace gossip 82 | 83 | } // namespace top 84 | -------------------------------------------------------------------------------- /tests/test_gossip_bloomfilter_layer.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include "xpbase/base/top_utils.h" 11 | #include "xpbase/base/line_parser.h" 12 | #include "xpbase/base/check_cast.h" 13 | #include "xpbase/base/xid/xid_def.h" 14 | #include "xpbase/base/xid/xid_generator.h" 15 | #include "xpbase/base/kad_key/platform_kadmlia_key.h" 16 | #define private public 17 | #include "xtransport/udp_transport/udp_transport.h" 18 | #include "xtransport/message_manager/multi_message_handler.h" 19 | #include "xkad/routing_table/routing_table.h" 20 | #include "xkad/routing_table/local_node_info.h" 21 | #include "xwrouter/multi_routing/multi_routing.h" 22 | #include "xwrouter/register_routing_table.h" 23 | #include "xgossip/include/broadcast_layered.h" 24 | #include "xgossip/include/gossip_bloomfilter_layer.h" 25 | 26 | namespace top { 27 | 28 | using namespace kadmlia; 29 | 30 | namespace gossip { 31 | 32 | namespace test { 33 | 34 | class TestGossipBloomfilterLayer : public testing::Test { 35 | public: 36 | enum TestRoutingType { 37 | 38 | }; 39 | static void SetUpTestCase() { 40 | } 41 | 42 | static void TearDownTestCase() { 43 | } 44 | 45 | virtual void SetUp() { 46 | } 47 | 48 | virtual void TearDown() { 49 | } 50 | 51 | RoutingTablePtr CreateRoutingTable(const std::string& peer) { 52 | std::string idtype(top::kadmlia::GenNodeIdType("CN", "VPN")); 53 | LocalNodeInfoPtr local_node_info; 54 | local_node_info.reset(new LocalNodeInfo()); 55 | auto kad_key = std::make_shared(); 56 | kad_key->set_xnetwork_id(kEdgeXVPN); 57 | kad_key->set_zone_id(check_cast(26)); 58 | local_node_info->Init( 59 | "0.0.0.0", 0, false, false, idtype, kad_key, kad_key->xnetwork_id(), kRoleEdge); 60 | local_node_info->set_public_ip("127.0.0.1"); 61 | local_node_info->set_public_port(10000); 62 | 63 | top::transport::TransportPtr udp_transport; 64 | udp_transport.reset(new top::transport::UdpTransport()); 65 | auto thread_message_handler = std::make_shared(); 66 | thread_message_handler->Init(); 67 | udp_transport->Start( 68 | "0.0.0.0", 69 | 0, 70 | thread_message_handler.get()); 71 | 72 | RoutingTablePtr routing_table_ptr; 73 | routing_table_ptr.reset(new top::kadmlia::RoutingTable( 74 | udp_transport, kNodeIdSize, local_node_info)); 75 | std::string bootstrap_path = "../../conf.ut/bootstrap.data"; 76 | top::wrouter::UnregisterRoutingTable(100); 77 | top::wrouter::RegisterRoutingTable(100, routing_table_ptr); 78 | return routing_table_ptr; 79 | } 80 | }; 81 | 82 | TEST_F(TestGossipBloomfilterLayer, GetBeginIndex) { 83 | } 84 | 85 | } // namespace test 86 | 87 | } // namespace gossip 88 | 89 | } // namespace top 90 | -------------------------------------------------------------------------------- /src/messages_with_bloomfilter.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "xbase/xpacket.h" 12 | #include "xtransport/proto/transport.pb.h" 13 | #include "xpbase/base/top_timer.h" 14 | #include "xgossip/include/header_block_data.h" 15 | #include "xtransport/message_manager/message_manager_intf.h" 16 | 17 | namespace top { 18 | 19 | namespace kadmlia { 20 | 21 | class RoutingTable; 22 | typedef std::shared_ptr RoutingTablePtr; 23 | 24 | } 25 | 26 | namespace gossip { 27 | 28 | struct SyncBlockItem { 29 | uint64_t routing_service_type; 30 | std::string header_hash; 31 | std::chrono::steady_clock::time_point time_point; 32 | }; 33 | 34 | class BlockSyncManager { 35 | public: 36 | static BlockSyncManager* Instance(); 37 | void SetLeagerFace(std::shared_ptr ledger_face); 38 | void SetRoutingTablePtr(kadmlia::RoutingTablePtr& routing_table); 39 | void NewBroadcastMessage(transport::protobuf::RoutingMessage& message); 40 | 41 | private: 42 | BlockSyncManager(); 43 | ~BlockSyncManager(); 44 | 45 | #include "xgossip/include/mesages_with_bloomfilter.h" 46 | 47 | #include "xbase/xhash.h" 48 | #include "xgossip/include/gossip_utils.h" 49 | #include "xpbase/base/top_log.h" 50 | 51 | namespace top { 52 | 53 | namespace gossip { 54 | 55 | MessageWithBloomfilter* MessageWithBloomfilter::Instance() { 56 | static MessageWithBloomfilter ins; 57 | return &ins; 58 | } 59 | 60 | std::shared_ptr MessageWithBloomfilter::GetMessageBloomfilter( 61 | transport::protobuf::RoutingMessage& message, 62 | bool& stop_gossip) { 63 | auto hash32 = message.gossip().msg_hash(); 64 | if (StopGossip(hash32, message.gossip().stop_times())) { 65 | stop_gossip = true; 66 | return nullptr; 67 | } 68 | 69 | std::vector new_bloomfilter_vec; 70 | for (auto i = 0; i < message.bloomfilter_size(); ++i) { 71 | new_bloomfilter_vec.push_back(message.bloomfilter(i)); 72 | } 73 | 74 | std::shared_ptr new_bloomfilter; 75 | if (new_bloomfilter_vec.empty()) { 76 | // readonly, mark static can improve performance 77 | static std::vector construct_vec(gossip::kGossipBloomfilterSize / 64, 0ull); 78 | new_bloomfilter = std::make_shared( 79 | construct_vec, 80 | gossip::kGossipBloomfilterHashNum); 81 | } else { 82 | new_bloomfilter = std::make_shared( 83 | new_bloomfilter_vec, 84 | gossip::kGossipBloomfilterHashNum); 85 | } 86 | // (Charlie): avoid evil 87 | // MergeBloomfilter(hash32, new_bloomfilter, message.gossip().stop_times(), stop_gossip); 88 | return new_bloomfilter; 89 | } 90 | 91 | bool MessageWithBloomfilter::StopGossip(const uint32_t& gossip_key, uint32_t stop_times) { 92 | if (stop_times <= 0) { 93 | stop_times = kGossipSendoutMaxTimes; 94 | } 95 | std::unique_lock lock(messsage_bloomfilter_map_mutex_); 96 | auto iter = messsage_bloomfilter_map_.find(gossip_key); 97 | if (iter != messsage_bloomfilter_map_.end()) { 98 | TOP_DEBUG("msg.hash:%d stop_times:%d", gossip_key, iter->second); 99 | if (iter->second >= stop_times) { 100 | return true; 101 | } 102 | ++(iter->second); 103 | } else { 104 | messsage_bloomfilter_map_[gossip_key] = 1; 105 | } 106 | 107 | 108 | // (Charlie): avoid memory crash 109 | if (messsage_bloomfilter_map_.size() >= kMaxMessageQueueSize) { 110 | messsage_bloomfilter_map_.clear(); 111 | } 112 | return false; 113 | } 114 | 115 | } // namespace gossip 116 | 117 | } // namespace top 118 | -------------------------------------------------------------------------------- /src/gossip_set_layer.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xgossip/include/gossip_set_layer.h" 6 | 7 | #include 8 | 9 | #include "xbase/xhash.h" 10 | #include "xbase/xcontext.h" 11 | #include "xbase/xbase.h" 12 | #include "xbasic/xhash.hpp" 13 | #include "xpbase/base/top_log.h" 14 | #include "xpbase/base/top_utils.h" 15 | #include "xpbase/base/uint64_bloomfilter.h" 16 | #include "xpbase/base/redis_client.h" 17 | #include "xgossip/include/gossip_utils.h" 18 | #include "xgossip/include/mesages_with_bloomfilter.h" 19 | #include "xgossip/include/block_sync_manager.h" 20 | #include "xpbase/base/redis_utils.h" 21 | 22 | namespace top { 23 | 24 | namespace gossip { 25 | 26 | GossipSetLayer::GossipSetLayer(transport::TransportPtr transport_ptr) 27 | : GossipInterface(transport_ptr) {} 28 | 29 | GossipSetLayer::~GossipSetLayer() {} 30 | 31 | void GossipSetLayer::Broadcast( 32 | uint64_t local_hash64, 33 | transport::protobuf::RoutingMessage& message, 34 | std::shared_ptr> prt_neighbors) { 35 | BlockSyncManager::Instance()->NewBroadcastMessage(message); 36 | if (message.gossip().max_hop_num() > 0 && 37 | message.gossip().max_hop_num() <= message.hop_num()) { 38 | TOP_WARN("message.type(%d) hop_num(%d) larger than gossip_max_hop_num(%d)", 39 | message.type(), 40 | message.hop_num(), 41 | message.gossip().max_hop_num()); 42 | return; 43 | } 44 | 45 | bool stop_gossip = false; 46 | auto hash64 = base::xhash64_t::digest(message.xid() + std::to_string(message.id())); 47 | auto bloomfilter = MessageWithBloomfilter::Instance()->StopGossip( 48 | hash64, 49 | message.gossip().stop_times()); 50 | if (stop_gossip) { 51 | TOP_DEBUG("stop gossip for message.type(%d)", message.type()); 52 | return; 53 | } 54 | 55 | auto gossip_param = message.mutable_gossip(); 56 | std::unordered_set passed_set(32); 57 | for (int i = 0; i < message.gossip().pass_node_size(); ++i) { 58 | passed_set.insert(message.gossip().pass_node(i)); 59 | } 60 | 61 | std::vector tmp_neighbors; 62 | 63 | for (auto iter = prt_neighbors->begin(); iter != prt_neighbors->end(); ++iter) { 64 | if ((*iter)->xid.empty()) { 65 | continue; 66 | } 67 | 68 | if (passed_set.find(static_cast((*iter)->hash64)) != passed_set.end()) { 69 | #ifdef TOP_TESTING_PERFORMANCE 70 | uint32_t filtered = 0; 71 | ++filtered; 72 | TOP_NETWORK_DEBUG_FOR_PROTOMESSAGE( 73 | std::string("message filterd: ") + (*iter)->public_ip + 74 | ":" + std::to_string((*iter)->public_port), message); 75 | #endif 76 | continue; 77 | } 78 | tmp_neighbors.push_back(*iter); 79 | } 80 | std::random_shuffle(tmp_neighbors.begin(), tmp_neighbors.end()); 81 | 82 | if (passed_set.find(static_cast(local_hash64)) == passed_set.end()) { 83 | gossip_param->add_pass_node(static_cast(local_hash64)); 84 | } 85 | #ifdef TOP_TESTING_PERFORMANCE 86 | std::string goed_ids; 87 | for (int i = 0; i < message.hop_nodes_size(); ++i) { 88 | goed_ids += HexEncode(message.hop_nodes(i).node_id()) + ","; 89 | } 90 | std::string data = base::StringUtil::str_fmt( 91 | "GossipSetLayer Broadcast tmp_neighbors size %d," 92 | "filtered %d nodes [hop num: %d][%s]", 93 | tmp_neighbors.size(), 94 | filtered, 95 | message.hop_num(), 96 | goed_ids.c_str()); 97 | TOP_NETWORK_DEBUG_FOR_PROTOMESSAGE(data, message); 98 | #endif 99 | std::vector rest_random_neighbors; 100 | std::vector dis_vec; 101 | if (message.hop_num() >= message.gossip().switch_layer_hop_num()) { 102 | SelectNodes(message, tmp_neighbors, rest_random_neighbors); 103 | } else { 104 | rest_random_neighbors = GetRandomNodes(tmp_neighbors, GetNeighborCount(message)); 105 | } 106 | 107 | for (auto iter = rest_random_neighbors.begin(); iter != rest_random_neighbors.end(); ++iter) { 108 | if (passed_set.find(static_cast((*iter)->hash64)) == passed_set.end()) { 109 | gossip_param->add_pass_node(static_cast((*iter)->hash64)); 110 | } 111 | } 112 | 113 | if (message.hop_num() >= message.gossip().switch_layer_hop_num()) { 114 | SendLayered(message, rest_random_neighbors); 115 | } else { 116 | Send(message, rest_random_neighbors); 117 | } 118 | } 119 | 120 | } // namespace gossip 121 | 122 | } // namespace top 123 | -------------------------------------------------------------------------------- /tests/test_broadcast_layered.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include "xpbase/base/top_utils.h" 11 | #include "xpbase/base/line_parser.h" 12 | #include "xpbase/base/check_cast.h" 13 | #include "xpbase/base/xid/xid_def.h" 14 | #include "xpbase/base/xid/xid_generator.h" 15 | #include "xpbase/base/kad_key/platform_kadmlia_key.h" 16 | #define private public 17 | #include "xtransport/udp_transport/udp_transport.h" 18 | #include "xtransport/message_manager/multi_message_handler.h" 19 | #include "xkad/routing_table/routing_table.h" 20 | #include "xkad/routing_table/local_node_info.h" 21 | #include "xwrouter/multi_routing/multi_routing.h" 22 | #include "xwrouter/register_routing_table.h" 23 | #include "xgossip/include/broadcast_layered.h" 24 | 25 | namespace top { 26 | 27 | using namespace kadmlia; 28 | 29 | namespace gossip { 30 | 31 | namespace test { 32 | 33 | class TestBroadcastLayered : public testing::Test { 34 | public: 35 | enum TestRoutingType { 36 | 37 | }; 38 | static void SetUpTestCase() { 39 | } 40 | 41 | static void TearDownTestCase() { 42 | } 43 | 44 | virtual void SetUp() { 45 | } 46 | 47 | virtual void TearDown() { 48 | } 49 | 50 | RoutingTablePtr CreateRoutingTable(const std::string& peer) { 51 | std::string idtype(top::kadmlia::GenNodeIdType("CN", "VPN")); 52 | LocalNodeInfoPtr local_node_info; 53 | local_node_info.reset(new LocalNodeInfo()); 54 | auto kad_key = std::make_shared(); 55 | kad_key->set_xnetwork_id(kEdgeXVPN); 56 | kad_key->set_zone_id(check_cast(26)); 57 | local_node_info->Init( 58 | "0.0.0.0", 0, false, false, idtype, kad_key, kad_key->xnetwork_id(), kRoleEdge); 59 | local_node_info->set_public_ip("127.0.0.1"); 60 | local_node_info->set_public_port(10000); 61 | 62 | top::transport::TransportPtr udp_transport; 63 | udp_transport.reset(new top::transport::UdpTransport()); 64 | auto thread_message_handler = std::make_shared(); 65 | thread_message_handler->Init(); 66 | udp_transport->Start( 67 | "0.0.0.0", 68 | 0, 69 | thread_message_handler.get()); 70 | 71 | RoutingTablePtr routing_table_ptr; 72 | routing_table_ptr.reset(new top::kadmlia::RoutingTable( 73 | udp_transport, kNodeIdSize, local_node_info)); 74 | std::string bootstrap_path = "../../conf.ut/bootstrap.data"; 75 | top::wrouter::UnregisterRoutingTable(100); 76 | top::wrouter::RegisterRoutingTable(100, routing_table_ptr); 77 | return routing_table_ptr; 78 | } 79 | }; 80 | 81 | TEST_F(TestBroadcastLayered, GetBeginIndex) { 82 | BroadcastLayered broadcast_layer(nullptr); 83 | ASSERT_EQ(broadcast_layer.GetBeginIndex(2, 1, 1), 3); 84 | ASSERT_EQ(broadcast_layer.GetBeginIndex(2, 2, 5), 11); 85 | ASSERT_EQ(broadcast_layer.GetBeginIndex(3, 1, 1), 4); 86 | ASSERT_EQ(broadcast_layer.GetBeginIndex(3, 1, 2), 7); 87 | ASSERT_EQ(broadcast_layer.GetBeginIndex(3, 1, 3), 10); 88 | ASSERT_EQ(broadcast_layer.GetBeginIndex(3, 2, 7), 22); 89 | } 90 | 91 | TEST_F(TestBroadcastLayered, ResortNodesWithSrcNode) { 92 | auto routing = CreateRoutingTable(""); 93 | std::vector nodes; 94 | for (int i = 0; i < 20; ++i) { 95 | std::string id = GenRandomID(10, 10); 96 | NodeInfoPtr node_ptr; 97 | node_ptr.reset(new NodeInfo(id)); 98 | node_ptr->local_ip = "127.0.0.1"; 99 | node_ptr->local_port = 1000 + i; 100 | node_ptr->public_ip = "127.0.0.1"; 101 | node_ptr->public_port = 1000 + i; 102 | nodes.push_back(node_ptr); 103 | } 104 | 105 | NodeInfoPtr rand_node = nodes[rand() % nodes.size()]; 106 | for (uint32_t i = 0; i < 3; ++i) { 107 | std::string target_xid = GenRandomID(10, 10); 108 | routing->SortNodesByTargetXid(target_xid, nodes); 109 | BroadcastLayered broadcast_layer(nullptr); 110 | std::vector r_nodes; 111 | broadcast_layer.ResortNodesWithSrcNode(nodes, rand_node->node_id, r_nodes); 112 | std::cout << "reorder: " << std::endl; 113 | std::cout << "src: " << HexEncode(rand_node->node_id) << std::endl; 114 | for (auto iter = r_nodes.begin(); iter != r_nodes.end(); ++iter) { 115 | std::cout << HexEncode((*iter)->node_id) << std::endl; 116 | } 117 | 118 | std::cout << "\n##############################################################" << std::endl; 119 | } 120 | } 121 | 122 | } // namespace test 123 | 124 | } // namespace gossip 125 | 126 | } // namespace top 127 | -------------------------------------------------------------------------------- /tests/test_ips.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | std::map> global_test_ips; 10 | 11 | inline void InitGlobalTestIps() { 12 | global_test_ips["0"] = std::vector{ 13 | "192.168.50.81", 14 | "192.168.50.82", 15 | "192.168.50.84" 16 | }; 17 | global_test_ips["1-0"] = std::vector{ 18 | "192.168.50.85", 19 | "192.168.50.86", 20 | "192.168.50.91", 21 | }; 22 | global_test_ips["1-1"] = std::vector{ 23 | "192.168.50.92", 24 | "192.168.50.94", 25 | "192.168.50.95", 26 | }; 27 | global_test_ips["1-2"] = std::vector{ 28 | "192.168.50.96", 29 | "192.168.50.97", 30 | "192.168.50.98", 31 | }; 32 | global_test_ips["2-0"] = std::vector{ 33 | "192.168.50.99", 34 | "192.168.50.100", 35 | "192.168.50.101", 36 | }; 37 | global_test_ips["2-1"] = std::vector{ 38 | "192.168.50.102", 39 | "192.168.50.104", 40 | "192.168.50.105", 41 | }; 42 | global_test_ips["2-2"] = std::vector{ 43 | "192.168.50.106", 44 | "192.168.50.111", 45 | "192.168.50.112", 46 | }; 47 | global_test_ips["2-3"] = std::vector{ 48 | "192.168.50.113", 49 | "192.168.50.114", 50 | "192.168.50.115", 51 | }; 52 | global_test_ips["2-4"] = std::vector{ 53 | "192.168.50.116", 54 | "192.168.50.117", 55 | "192.168.50.118", 56 | }; 57 | global_test_ips["2-5"] = std::vector{ 58 | "192.168.50.119", 59 | "192.168.50.120", 60 | "192.168.50.164", 61 | }; 62 | global_test_ips["2-6"] = std::vector{ 63 | "192.168.50.165", 64 | "192.168.50.166", 65 | "192.168.50.147", 66 | }; 67 | global_test_ips["2-7"] = std::vector{ 68 | "192.168.50.161", 69 | "192.168.50.123", 70 | "192.168.50.124", 71 | }; 72 | global_test_ips["2-8"] = std::vector{ 73 | "192.168.50.125", 74 | "192.168.50.126", 75 | "192.168.50.131", 76 | }; 77 | global_test_ips["3-0"] = std::vector{ 78 | "192.168.50.132", 79 | "192.168.50.133", 80 | "192.168.50.134", 81 | }; 82 | global_test_ips["3-1"] = std::vector{ 83 | "192.168.50.135", 84 | "192.168.50.136", 85 | "192.168.50.137", 86 | }; 87 | global_test_ips["3-2"] = std::vector{ 88 | "192.168.50.138", 89 | "192.168.50.139", 90 | "192.168.50.141", 91 | }; 92 | global_test_ips["3-3"] = std::vector{ 93 | "192.168.50.142", 94 | "192.168.50.143", 95 | "192.168.50.144", 96 | }; 97 | global_test_ips["3-4"] = std::vector{ 98 | "192.168.50.162", 99 | "192.168.50.163", 100 | "192.168.50.140" 101 | }; 102 | } 103 | static std::vector global_test_ip_vec{ 104 | // 0 105 | "192.168.50.81", 106 | "192.168.50.82", 107 | "192.168.50.84", 108 | // 1 109 | "192.168.50.85", 110 | "192.168.50.86", 111 | "192.168.50.91", 112 | 113 | "192.168.50.92", 114 | "192.168.50.94", 115 | "192.168.50.95", 116 | 117 | "192.168.50.96", 118 | "192.168.50.97", 119 | "192.168.50.98", 120 | // 2 -0 121 | "192.168.50.99", 122 | "192.168.50.100", 123 | "192.168.50.101", 124 | // 2 -1 125 | 126 | "192.168.50.102", 127 | "192.168.50.104", 128 | "192.168.50.105", 129 | // 2 -2 130 | 131 | "192.168.50.106", 132 | "192.168.50.111", 133 | "192.168.50.112", 134 | // 2 -3 135 | 136 | "192.168.50.113", 137 | "192.168.50.114", 138 | "192.168.50.115", 139 | // 2 -4 140 | 141 | "192.168.50.116", 142 | "192.168.50.117", 143 | "192.168.50.118", 144 | // 2 -5 145 | 146 | "192.168.50.119", 147 | "192.168.50.120", 148 | "192.168.50.164", 149 | // 2 -6 150 | 151 | "192.168.50.165", 152 | "192.168.50.166", 153 | "192.168.50.147", 154 | // 2 -7 155 | 156 | "192.168.50.161", 157 | "192.168.50.123", 158 | "192.168.50.124", 159 | // 2 -8 160 | 161 | "192.168.50.125", 162 | "192.168.50.126", 163 | "192.168.50.131", 164 | // 3 - 0 165 | "192.168.50.132", 166 | "192.168.50.133", 167 | "192.168.50.134", 168 | // 3 - 1 169 | 170 | "192.168.50.135", 171 | "192.168.50.136", 172 | "192.168.50.137", 173 | // 3 - 2 174 | 175 | "192.168.50.138", 176 | "192.168.50.139", 177 | "192.168.50.141", 178 | // 3 - 3 179 | 180 | "192.168.50.142", 181 | "192.168.50.143", 182 | "192.168.50.144", 183 | // 3 - 4 184 | 185 | "192.168.50.162", 186 | "192.168.50.163", 187 | "192.168.50.140" 188 | }; 189 | -------------------------------------------------------------------------------- /src/gossip_bloomfilter.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xgossip/include/gossip_bloomfilter.h" 6 | 7 | #include "xbase/xhash.h" 8 | #include "xbase/xcontext.h" 9 | #include "xbase/xbase.h" 10 | #include "xpbase/base/top_log.h" 11 | #include "xpbase/base/top_utils.h" 12 | #include "xpbase/base/uint64_bloomfilter.h" 13 | #include "xpbase/base/redis_client.h" 14 | #include "xgossip/include/gossip_utils.h" 15 | #include "xgossip/include/mesages_with_bloomfilter.h" 16 | #include "xgossip/include/block_sync_manager.h" 17 | #include "xpbase/base/redis_utils.h" 18 | 19 | namespace top { 20 | 21 | namespace gossip { 22 | 23 | GossipBloomfilter::GossipBloomfilter(transport::TransportPtr transport_ptr) 24 | : GossipInterface(transport_ptr) {} 25 | 26 | GossipBloomfilter::~GossipBloomfilter() {} 27 | 28 | void GossipBloomfilter::Broadcast( 29 | uint64_t local_hash64, 30 | transport::protobuf::RoutingMessage& message, 31 | std::shared_ptr> prt_neighbors) { 32 | auto neighbors = *prt_neighbors; 33 | TOP_NETWORK_DEBUG_FOR_REDIS(message, "recv_count"); 34 | 35 | TOP_DEBUG("GossipBloomfilter Broadcast neighbors size %d", neighbors.size()); 36 | 37 | BlockSyncManager::Instance()->NewBroadcastMessage(message); 38 | if (message.gossip().max_hop_num() > 0 && 39 | message.gossip().max_hop_num() <= message.hop_num()) { 40 | TOP_WARN2("message.type(%d) hop_num(%d) larger than gossip_max_hop_num(%d)", 41 | message.type(), 42 | message.hop_num(), 43 | message.gossip().max_hop_num()); 44 | return; 45 | } 46 | 47 | if (ThisNodeIsEvil(message)) { 48 | TOP_WARN2("this node(%s) is evil", HexEncode(global_xid->Get()).c_str()); 49 | return; 50 | } 51 | bool stop_gossip = false; 52 | auto bloomfilter = MessageWithBloomfilter::Instance()->GetMessageBloomfilter( 53 | message, 54 | stop_gossip); 55 | if (stop_gossip) { 56 | TOP_NETWORK_DEBUG_FOR_REDIS(message, "hop_num"); 57 | TOP_DEBUG("stop gossip for message.type(%d) hop_num(%d)", message.type(), message.hop_num()); 58 | return; 59 | } 60 | 61 | assert(bloomfilter); 62 | if (!bloomfilter) { 63 | TOP_WARN2("bloomfilter invalid"); 64 | return; 65 | } 66 | bloomfilter->Add(local_hash64); 67 | 68 | std::vector tmp_neighbors; 69 | uint32_t filtered = 0; 70 | for (auto iter = neighbors.begin(); iter != neighbors.end(); ++iter) { 71 | if ((*iter)->hash64 == 0) { 72 | TOP_WARN("node:%s hash64 empty, invalid", HexEncode((*iter)->xid).c_str()); 73 | continue; 74 | } 75 | 76 | if (bloomfilter->Contain((*iter)->hash64)) { 77 | ++filtered; 78 | #ifdef TOP_TESTING_PERFORMANCE 79 | TOP_NETWORK_DEBUG_FOR_PROTOMESSAGE( 80 | std::string("message filterd: ") + (*iter)->public_ip + 81 | ":" + std::to_string((*iter)->public_port), message); 82 | #endif 83 | continue; 84 | } 85 | 86 | tmp_neighbors.push_back(*iter); 87 | } 88 | TOP_DEBUG("GossipBloomfilter Broadcast tmp_neighbors size %d, filtered %d nodes", 89 | tmp_neighbors.size(), 90 | filtered); 91 | 92 | std::vector rest_random_neighbors; 93 | rest_random_neighbors = GetRandomNodes(tmp_neighbors, GetNeighborCount(message)); 94 | if (rest_random_neighbors.empty()) { 95 | TOP_WARN2("stop Broadcast, rest_random_neighbors empty, broadcast failed, msg.hop_num(%d), msg.type(%d)", 96 | message.hop_num(), 97 | message.type()); 98 | return; 99 | } 100 | 101 | if (message.hop_num() > message.gossip().ign_bloomfilter_level()) { 102 | for (auto iter = rest_random_neighbors.begin(); 103 | iter != rest_random_neighbors.end(); ++iter) { 104 | bloomfilter->Add((*iter)->hash64); 105 | } 106 | } 107 | 108 | const std::vector& bloomfilter_vec = bloomfilter->Uint64Vector(); 109 | message.clear_bloomfilter(); 110 | for (uint32_t i = 0; i < bloomfilter_vec.size(); ++i) { 111 | message.add_bloomfilter(bloomfilter_vec[i]); 112 | } 113 | 114 | TOP_DEBUG("GossipBloomfilter Broadcast finally %d neighbors", rest_random_neighbors.size()); 115 | Send(message, rest_random_neighbors); 116 | 117 | TOP_NETWORK_DEBUG_FOR_REDIS(message, "hop_num"); 118 | } 119 | 120 | void GossipBloomfilter::BroadcastWithNoFilter( 121 | const std::string& local_id, 122 | transport::protobuf::RoutingMessage& message, 123 | const std::vector& neighbors) { 124 | TOP_DEBUG("GossipBloomfilter Broadcast neighbors size %d", neighbors.size()); 125 | 126 | BlockSyncManager::Instance()->NewBroadcastMessage(message); 127 | if (message.gossip().max_hop_num() > 0 && 128 | message.gossip().max_hop_num() <= message.hop_num()) { 129 | TOP_WARN2("message.type(%d) hop_num(%d) larger than gossip_max_hop_num(%d)", 130 | message.type(), 131 | message.hop_num(), 132 | message.gossip().max_hop_num()); 133 | return; 134 | } 135 | 136 | if (ThisNodeIsEvil(message)) { 137 | TOP_WARN2("this node(%s) is evil", HexEncode(local_id).c_str()); 138 | return; 139 | } 140 | Send(message, neighbors); 141 | } 142 | 143 | } // namespace gossip 144 | 145 | } // namespace top 146 | -------------------------------------------------------------------------------- /tests/test_gossip_interface.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include "xpbase/base/top_utils.h" 11 | #include "xpbase/base/line_parser.h" 12 | #include "xpbase/base/check_cast.h" 13 | #include "xpbase/base/xid/xid_def.h" 14 | #include "xpbase/base/xid/xid_generator.h" 15 | #include "xpbase/base/kad_key/platform_kadmlia_key.h" 16 | #define private public 17 | #define protected public 18 | #include "xtransport/udp_transport/udp_transport.h" 19 | #include "xtransport/message_manager/multi_message_handler.h" 20 | #include "xkad/routing_table/routing_table.h" 21 | #include "xkad/routing_table/local_node_info.h" 22 | #include "xwrouter/multi_routing/multi_routing.h" 23 | #include "xwrouter/register_routing_table.h" 24 | #include "xgossip/include/broadcast_layered.h" 25 | #include "xgossip/include/gossip_bloomfilter_layer.h" 26 | 27 | namespace top { 28 | 29 | using namespace kadmlia; 30 | 31 | namespace gossip { 32 | 33 | namespace test { 34 | 35 | class TestGossipInterface : public testing::Test { 36 | public: 37 | enum TestRoutingType {}; 38 | 39 | static void SetUpTestCase() {} 40 | 41 | static void TearDownTestCase() {} 42 | 43 | virtual void SetUp() {} 44 | 45 | virtual void TearDown() {} 46 | void Chooselayer( 47 | std::vector& nodes, 48 | transport::protobuf::RoutingMessage message, 49 | std::vector& msg_vec) { 50 | std::vector select_nodes; 51 | GossipBloomfilterLayer bloom_layer(nullptr); 52 | bloom_layer.SelectNodes(message, nodes, select_nodes); 53 | std::cout << "select nodes: "; 54 | for (uint32_t i = 0; i < select_nodes.size(); ++i) { 55 | std::cout << select_nodes[i]->hash64 << " "; 56 | } 57 | std::cout << std::endl; 58 | 59 | uint64_t min_dis = message.gossip().min_dis(); 60 | uint64_t max_dis = message.gossip().max_dis(); 61 | if (max_dis <= 0) { 62 | max_dis = std::numeric_limits::max(); 63 | } 64 | 65 | for (uint32_t i = 0; i < select_nodes.size(); ++i) { 66 | auto gossip = message.mutable_gossip(); 67 | if (i == 0) { 68 | gossip->set_min_dis(min_dis); 69 | gossip->set_left_min(min_dis); 70 | 71 | if (select_nodes.size() == 1) { 72 | gossip->set_max_dis(max_dis); 73 | gossip->set_right_max(max_dis); 74 | } else { 75 | gossip->set_max_dis(select_nodes[0]->hash64); 76 | gossip->set_right_max(select_nodes[1]->hash64); 77 | } 78 | } 79 | 80 | if (i > 0 && i < (select_nodes.size() - 1)) { 81 | gossip->set_min_dis(select_nodes[i - 1]->hash64); 82 | gossip->set_max_dis(select_nodes[i]->hash64); 83 | 84 | if (i == 1) { 85 | gossip->set_left_min(min_dis); 86 | } else { 87 | gossip->set_left_min(select_nodes[i - 2]->hash64); 88 | } 89 | gossip->set_right_max(select_nodes[i + 1]->hash64); 90 | } 91 | 92 | if (i > 0 && i == (select_nodes.size() - 1)) { 93 | gossip->set_min_dis(select_nodes[i - 1]->hash64); 94 | gossip->set_max_dis(max_dis); 95 | 96 | if (i == 1) { 97 | gossip->set_left_min(min_dis); 98 | } else { 99 | gossip->set_left_min(select_nodes[i - 2]->hash64); 100 | } 101 | gossip->set_right_max(max_dis); 102 | } 103 | 104 | std::cout << i << ": " << gossip->min_dis() << ":" << gossip->max_dis() 105 | << " , " << gossip->left_min() << ":" << gossip->right_max() << std::endl; 106 | msg_vec.push_back(message); 107 | } 108 | } 109 | }; 110 | 111 | TEST_F(TestGossipInterface, SelectNodesNoOverlap) { 112 | std::vector nodes; 113 | uint64_t local_hash = base::xhash64_t::digest(RandomString(kNodeIdSize)); 114 | for (uint32_t i = 0; i < 10240; ++i) { 115 | auto node_ptr = std::make_shared(RandomString(kNodeIdSize)); 116 | node_ptr->hash64 = i; 117 | nodes.push_back(node_ptr); 118 | } 119 | std::random_shuffle(nodes.begin(), nodes.end()); 120 | transport::protobuf::RoutingMessage message; 121 | auto gossip_param = message.mutable_gossip(); 122 | gossip_param->set_min_dis(0); 123 | gossip_param->set_max_dis(std::numeric_limits::max()); 124 | gossip_param->set_neighber_count(3); 125 | std::vector msg_vec; 126 | Chooselayer(nodes, message, msg_vec); 127 | int layer_num = 1; 128 | for (uint32_t layer_num = 1; layer_num < 10; ++layer_num) { 129 | std::cout << "layer: " << layer_num++ << std::endl; 130 | std::vector tmp_msg_vec; 131 | for (uint32_t i = 0; i < msg_vec.size(); ++i) { 132 | std::vector tmp_vec; 133 | Chooselayer(nodes, msg_vec[i], tmp_vec); 134 | for (uint32_t i = 0; i < tmp_vec.size(); ++i) { 135 | tmp_msg_vec.push_back(tmp_vec[i]); 136 | } 137 | } 138 | msg_vec = tmp_msg_vec; 139 | std::cout << std::endl; 140 | } 141 | } 142 | 143 | } // namespace test 144 | 145 | } // namespace gossip 146 | 147 | } // namespace top 148 | -------------------------------------------------------------------------------- /src/gossip_filter.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xgossip/include/gossip_filter.h" 6 | 7 | #include 8 | 9 | #include "xpbase/base/top_log.h" 10 | #include "xpbase/base/top_timer.h" 11 | #include "xpbase/base/kad_key/kadmlia_key.h" 12 | 13 | namespace top { 14 | 15 | namespace gossip { 16 | 17 | GossipFilter* GossipFilter::Instance() { 18 | static GossipFilter ins; 19 | 20 | 21 | return &ins; 22 | } 23 | 24 | bool GossipFilter::Init() { 25 | assert(!inited_); 26 | for (uint32_t i = 0; i < 3; ++i) { 27 | auto hash_ptr = std::make_shared>(); 28 | time_filter_.push_back(hash_ptr); 29 | } 30 | timer_ = std::make_shared(base::TimerManager::Instance(), "GossipFilter"); 31 | timer_->Start( 32 | 500ll * 1000ll, 33 | kClearRstPeriod, 34 | std::bind(&GossipFilter::do_clear_and_reset, this)); 35 | 36 | #ifndef NDEBUG 37 | remap_timer_ = std::make_shared(base::TimerManager::Instance(), "GossipFilter:repeatmap"); 38 | remap_timer_->Start( 39 | 500ll * 1000ll, 40 | kClearRstPeriod, 41 | std::bind(&GossipFilter::PrintRepeatMap, this)); 42 | #endif 43 | 44 | inited_ = true; 45 | return true; 46 | } 47 | 48 | GossipFilter::GossipFilter() { 49 | } 50 | 51 | GossipFilter::~GossipFilter() { 52 | timer_->Join(); 53 | remap_timer_->Join(); 54 | timer_ = nullptr; 55 | remap_timer_ = nullptr; 56 | } 57 | 58 | void GossipFilter::AddRepeatMsg(uint32_t key) { 59 | #ifndef NDEBUG 60 | std::unique_lock lock(repeat_map_mutex_); 61 | repeat_map_[key] += 1; 62 | #endif 63 | } 64 | 65 | void GossipFilter::PrintRepeatMap() { 66 | #ifndef NDEBUG 67 | { 68 | std::unique_lock lock(repeat_map_mutex_); 69 | if (repeat_map_.size() <= 0) { 70 | return; 71 | } 72 | uint32_t total_recv_count = 0; 73 | uint32_t max_recv = 0; 74 | for (auto& item : repeat_map_) { 75 | auto key = item.first; 76 | auto value = item.second; 77 | total_recv_count += value; 78 | if (value > max_recv) { 79 | max_recv = value; 80 | } 81 | } 82 | auto avg_recv_times = total_recv_count / repeat_map_.size(); 83 | TOP_DEBUG("gossipfilter repeat recv avg:%d max:%d mapsize:%d", avg_recv_times, max_recv, repeat_map_.size()); 84 | 85 | // do clear 86 | if (repeat_map_.size() > 100000) { 87 | repeat_map_.clear(); 88 | } 89 | } 90 | #endif 91 | } 92 | 93 | bool GossipFilter::FilterMessage(transport::protobuf::RoutingMessage& message) { 94 | assert(inited_); 95 | auto gossip = message.gossip(); 96 | if (!gossip.has_msg_hash()) { 97 | TOP_WARN("filter failed, gossip msg(%d) should set msg_hash", message.type()); 98 | return true;; 99 | } 100 | #ifndef NDEBUG 101 | AddRepeatMsg(gossip.msg_hash()); 102 | #endif 103 | if (message.xid() == global_xid->Get()) { 104 | TOP_WARN("message come back this original node,msg.type(%d)", message.type()); 105 | return true; 106 | } 107 | if (FindData(gossip.msg_hash())) { 108 | TOP_DEBUG("GossipFilter FindData, filter msg"); 109 | return true; 110 | } 111 | if (!AddData(gossip.msg_hash())) { 112 | TOP_WARN("GossipFilter already exist, filter msg"); 113 | return true; 114 | } 115 | return false; 116 | } 117 | 118 | bool GossipFilter::FindData(uint32_t key) { 119 | assert(current_index_ < 3 && current_index_ >= 0); 120 | std::unique_lock lock(current_index_mutex_); 121 | auto it_find = time_filter_[current_index_]->find(key); 122 | if (it_find != time_filter_[current_index_]->end()) { 123 | return it_find->second >= kRepeatedValue; 124 | } 125 | // last available index 126 | uint32_t last_index = (current_index_ + 2) % 3; 127 | auto last_it_find = time_filter_[last_index]->find(key); 128 | if (last_it_find != time_filter_[last_index]->end()) { 129 | return last_it_find->second >= kRepeatedValue; 130 | } 131 | return false; 132 | } 133 | 134 | bool GossipFilter::AddData(uint32_t key) { 135 | assert(current_index_ < 3 && current_index_ >= 0); 136 | std::unique_lock lock(current_index_mutex_); 137 | auto it_find = time_filter_[current_index_]->find(key); 138 | if (it_find != time_filter_[current_index_]->end()) { 139 | if (it_find->second >= kRepeatedValue) { 140 | return false; 141 | } 142 | ++it_find->second; 143 | return true; 144 | } 145 | 146 | // last available index 147 | uint32_t last_index = (current_index_ + 2) % 3; 148 | auto last_it_find = time_filter_[last_index]->find(key); 149 | if (last_it_find != time_filter_[last_index]->end()) { 150 | if (last_it_find->second >= kRepeatedValue) { 151 | return false; 152 | } 153 | ++last_it_find->second; 154 | return true; 155 | } 156 | 157 | time_filter_[current_index_]->insert(std::make_pair(key, 1)); 158 | return true; 159 | } 160 | 161 | void GossipFilter::do_clear_and_reset() { 162 | { 163 | assert(current_index_ < 3 && current_index_ >= 0); 164 | std::unique_lock lock(current_index_mutex_); 165 | uint32_t not_used_index = (current_index_ + 1) % 3; 166 | time_filter_[not_used_index]->clear(); 167 | current_index_ = not_used_index; 168 | } 169 | } 170 | 171 | } // end namespace gossip 172 | 173 | } // end namespace top 174 | -------------------------------------------------------------------------------- /src/gossip_bloomfilter_layer.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xgossip/include/gossip_bloomfilter_layer.h" 6 | 7 | #include "xbase/xhash.h" 8 | #include "xbase/xcontext.h" 9 | #include "xbase/xbase.h" 10 | #include "xpbase/base/top_log.h" 11 | #include "xpbase/base/top_utils.h" 12 | #include "xpbase/base/uint64_bloomfilter.h" 13 | #include "xpbase/base/redis_client.h" 14 | #include "xgossip/include/gossip_utils.h" 15 | #include "xgossip/include/mesages_with_bloomfilter.h" 16 | #include "xgossip/include/block_sync_manager.h" 17 | #include "xpbase/base/redis_utils.h" 18 | 19 | namespace top { 20 | 21 | namespace gossip { 22 | 23 | GossipBloomfilterLayer::GossipBloomfilterLayer(transport::TransportPtr transport_ptr) 24 | : GossipInterface(transport_ptr) {} 25 | 26 | GossipBloomfilterLayer::~GossipBloomfilterLayer() {} 27 | 28 | void GossipBloomfilterLayer::Broadcast( 29 | uint64_t local_hash64, 30 | transport::protobuf::RoutingMessage& message, 31 | std::shared_ptr> prt_neighbors) { 32 | /* 33 | CheckDiffNetwork(message); 34 | BlockSyncManager::Instance()->NewBroadcastMessage(message); 35 | if (message.gossip().max_hop_num() > 0 && 36 | message.gossip().max_hop_num() <= message.hop_num()) { 37 | TOP_WARN2("message.type(%d) hop_num(%d) larger than gossip_max_hop_num(%d)", 38 | message.type(), 39 | message.hop_num(), 40 | message.gossip().max_hop_num()); 41 | return; 42 | } 43 | 44 | bool stop_gossip = false; 45 | auto bloomfilter = MessageWithBloomfilter::Instance()->GetMessageBloomfilter( 46 | message, 47 | stop_gossip); 48 | if (stop_gossip) { 49 | TOP_DEBUG("stop gossip for message.type(%d) hop_num(%d)", message.type(), message.hop_num()); 50 | return; 51 | } 52 | 53 | assert(bloomfilter); 54 | if (!bloomfilter) { 55 | TOP_WARN2("bloomfilter invalid"); 56 | return; 57 | } 58 | std::vector tmp_neighbors; 59 | 60 | auto gossip_param = message.mutable_gossip(); 61 | uint32_t filtered = 0; 62 | for (auto iter = prt_neighbors->begin(); iter != prt_neighbors->end(); ++iter) { 63 | if (!IsIpValid((*iter)->public_ip)) { 64 | continue; 65 | } 66 | 67 | if ((*iter)->hash64 == 0) { 68 | continue; 69 | } 70 | 71 | if (bloomfilter->Contain((*iter)->hash64)) { 72 | ++filtered; 73 | #ifdef TOP_TESTING_PERFORMANCE 74 | TOP_NETWORK_DEBUG_FOR_PROTOMESSAGE( 75 | std::string("message filterd: ") + (*iter)->public_ip + 76 | ":" + std::to_string((*iter)->public_port), message); 77 | #endif 78 | continue; 79 | } 80 | 81 | if ((*iter)->public_ip == gossip_param->pre_ip() && 82 | (*iter)->public_port == gossip_param->pre_port()) { 83 | if (message.hop_num() > message.gossip().ign_bloomfilter_level()) { 84 | bloomfilter->Add((*iter)->hash64); 85 | } 86 | continue; 87 | } 88 | tmp_neighbors.push_back(*iter); 89 | } 90 | 91 | TOP_DEBUG("GossipBloomfilterLayer Broadcast tmp_neighbors size %d, filtered %d nodes", 92 | tmp_neighbors.size(), 93 | filtered); 94 | std::random_shuffle(tmp_neighbors.begin(), tmp_neighbors.end()); 95 | 96 | if (message.hop_num() > message.gossip().ign_bloomfilter_level()) { 97 | bloomfilter->Add(local_hash64); 98 | } 99 | #ifdef TOP_TESTING_PERFORMANCE 100 | std::string goed_ids; 101 | for (uint32_t i = 0; i < message.hop_nodes_size(); ++i) { 102 | goed_ids += HexEncode(message.hop_nodes(i).node_id()) + ","; 103 | } 104 | std::string data = base::StringUtil::str_fmt( 105 | "GossipBloomfilterLayer Broadcast tmp_neighbors size %d," 106 | "filtered %d nodes [hop num: %d][%s][%s]", 107 | tmp_neighbors.size(), 108 | filtered, 109 | message.hop_num(), 110 | goed_ids.c_str(), 111 | bloomfilter->string().c_str()); 112 | TOP_NETWORK_DEBUG_FOR_PROTOMESSAGE(data, message); 113 | #endif 114 | std::vector rest_random_neighbors; 115 | if (message.hop_num() >= message.gossip().switch_layer_hop_num()) { 116 | SelectNodes(message, tmp_neighbors, rest_random_neighbors); 117 | } else { 118 | rest_random_neighbors = GetRandomNodes(tmp_neighbors, GetNeighborCount(message)); 119 | } 120 | 121 | if ((message.hop_num() + 1) > message.gossip().ign_bloomfilter_level()) { 122 | for (auto iter = rest_random_neighbors.begin(); 123 | iter != rest_random_neighbors.end(); ++iter) { 124 | bloomfilter->Add((*iter)->hash64); 125 | } 126 | } 127 | const std::vector& bloomfilter_vec = bloomfilter->Uint64Vector(); 128 | message.clear_bloomfilter(); 129 | for (uint32_t i = 0; i < bloomfilter_vec.size(); ++i) { 130 | message.add_bloomfilter(bloomfilter_vec[i]); 131 | } 132 | if (rest_random_neighbors.empty()) { 133 | TOP_WARN2("rest_random_neighbors empty, broadcast failed"); 134 | return; 135 | } 136 | 137 | gossip_param->clear_pre_ip(); 138 | gossip_param->clear_pre_port(); 139 | if (message.hop_num() >= message.gossip().switch_layer_hop_num()) { 140 | SendLayered(message, rest_random_neighbors); 141 | } else { 142 | Send(message, rest_random_neighbors); 143 | } 144 | */ 145 | } 146 | 147 | void GossipBloomfilterLayer::Broadcast( 148 | transport::protobuf::RoutingMessage& message, 149 | kadmlia::RoutingTablePtr& routing_table) { 150 | CheckDiffNetwork(message); 151 | BlockSyncManager::Instance()->NewBroadcastMessage(message); 152 | if (message.gossip().max_hop_num() > 0 && 153 | message.gossip().max_hop_num() <= message.hop_num()) { 154 | TOP_WARN2("message.type(%d) hop_num(%d) larger than gossip_max_hop_num(%d)", 155 | message.type(), 156 | message.hop_num(), 157 | message.gossip().max_hop_num()); 158 | return; 159 | } 160 | 161 | bool stop_gossip = false; 162 | auto bloomfilter = MessageWithBloomfilter::Instance()->GetMessageBloomfilter( 163 | message, 164 | stop_gossip); 165 | if (stop_gossip) { 166 | TOP_DEBUG("stop gossip for message.type(%d) hop_num(%d)", message.type(), message.hop_num()); 167 | return; 168 | } 169 | 170 | assert(bloomfilter); 171 | if (!bloomfilter) { 172 | TOP_WARN2("bloomfilter invalid"); 173 | return; 174 | } 175 | 176 | if (message.hop_num() >= message.gossip().ign_bloomfilter_level()) { 177 | bloomfilter->Add(routing_table->get_local_node_info()->hash64()); 178 | } 179 | 180 | std::vector select_nodes; 181 | SelectNodes(message, routing_table, bloomfilter, select_nodes); 182 | if (select_nodes.empty()) { 183 | TOP_WARN2("stop broadcast, select_nodes empty, msg.hop_num(%d), msg.type(%d)", 184 | message.hop_num(), 185 | message.type()); 186 | return; 187 | } 188 | 189 | #ifdef TOP_TESTING_PERFORMANCE 190 | std::string goed_ids; 191 | for (uint32_t i = 0; i < message.hop_nodes_size(); ++i) { 192 | goed_ids += HexEncode(message.hop_nodes(i).node_id()) + ","; 193 | } 194 | std::string data = base::StringUtil::str_fmt( 195 | "GossipBloomfilterLayer Broadcast select_node size %d," 196 | "filtered %d nodes [hop num: %d][%s][%s]", 197 | select_nodes.size(), 198 | filtered, 199 | message.hop_num(), 200 | goed_ids.c_str(), 201 | bloomfilter->string().c_str()); 202 | TOP_NETWORK_DEBUG_FOR_PROTOMESSAGE(data, message); 203 | #endif 204 | 205 | if ((message.hop_num() + 1) > message.gossip().ign_bloomfilter_level()) { 206 | for (auto iter = select_nodes.begin(); 207 | iter != select_nodes.end(); ++iter) { 208 | bloomfilter->Add((*iter)->hash64); 209 | } 210 | } 211 | const std::vector& bloomfilter_vec = bloomfilter->Uint64Vector(); 212 | message.clear_bloomfilter(); 213 | for (uint32_t i = 0; i < bloomfilter_vec.size(); ++i) { 214 | message.add_bloomfilter(bloomfilter_vec[i]); 215 | } 216 | 217 | if (message.hop_num() >= message.gossip().switch_layer_hop_num()) { 218 | SendLayered(message, select_nodes); 219 | } else { 220 | Send(message, select_nodes); 221 | } 222 | } 223 | 224 | } // namespace gossip 225 | 226 | } // namespace top 227 | -------------------------------------------------------------------------------- /src/broadcast_layered.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xgossip/include/broadcast_layered.h" 6 | 7 | #include 8 | 9 | #include "xpbase/base/redis_client.h" 10 | #include "xkad/routing_table/routing_table.h" 11 | #include "xgossip/include/gossip_utils.h" 12 | #include "xgossip/include/block_sync_manager.h" 13 | 14 | namespace top { 15 | 16 | using namespace kadmlia; 17 | 18 | namespace gossip { 19 | 20 | BroadcastLayered::BroadcastLayered(transport::TransportPtr transport_ptr) 21 | : GossipInterface(transport_ptr) {} 22 | 23 | BroadcastLayered::~BroadcastLayered() {} 24 | 25 | void BroadcastLayered::Broadcast( 26 | transport::protobuf::RoutingMessage& message, 27 | kadmlia::RoutingTablePtr& routing_table) { 28 | if (message.hop_num() >= kadmlia::kHopToLive) { 29 | TOP_WARN2("message hop_num(%d) beyond max_hop", message.hop_num()); 30 | return; 31 | } 32 | 33 | if (ThisNodeIsEvil(message)) { 34 | TOP_WARN2("this node(%s) is evil", HexEncode(global_xid->Get()).c_str()); 35 | return; 36 | } 37 | BlockSyncManager::Instance()->NewBroadcastMessage(message); 38 | 39 | std::vector broadcast_nodes; 40 | GetNextBroadcastNodes( 41 | message, 42 | routing_table, 43 | broadcast_nodes); 44 | Send(message, broadcast_nodes); 45 | } 46 | 47 | uint32_t BroadcastLayered::FindLogicalSelfIndex( 48 | uint32_t real_self_index, 49 | uint32_t random_step, 50 | uint32_t nodes_size) { 51 | assert(real_self_index > 0 && real_self_index <= nodes_size); 52 | uint32_t logical_self_index = (real_self_index + random_step) % nodes_size; 53 | logical_self_index = (logical_self_index == 0)?nodes_size:logical_self_index; 54 | return logical_self_index; 55 | } 56 | 57 | uint32_t BroadcastLayered::FindRealSelfIndex( 58 | uint32_t logical_self_index, 59 | uint32_t random_step, 60 | uint32_t nodes_size) { 61 | assert(logical_self_index > 0 && logical_self_index <= nodes_size); 62 | if (logical_self_index <= random_step) { 63 | return (logical_self_index + nodes_size) - random_step; 64 | } else { 65 | return logical_self_index - random_step; 66 | } 67 | } 68 | 69 | void BroadcastLayered::GetRangeNodes( 70 | kadmlia::RoutingTablePtr& routing_table, 71 | const uint32_t& min_index, 72 | const uint32_t& max_index, 73 | std::vector& vec) { 74 | uint32_t nodes_size = routing_table->nodes_size() + 1; 75 | if (min_index <= max_index) { 76 | return routing_table->GetRangeNodes(min_index, max_index, vec); 77 | } 78 | // may be on a ring loop 79 | routing_table->GetRangeNodes(0, max_index, vec); 80 | routing_table->GetRangeNodes(min_index, nodes_size - 1, vec); 81 | return; 82 | } 83 | 84 | void BroadcastLayered::GetNextBroadcastNodes( 85 | transport::protobuf::RoutingMessage& message, 86 | kadmlia::RoutingTablePtr& routing_table, 87 | std::vector& next_broadcast_nodes) { 88 | uint32_t nodes_size = routing_table->nodes_size() + 1; // including self 89 | //uint32_t random_step = 0; 90 | uint32_t random_step = message.id() % nodes_size; // keep same random_step when this broadcast message alive 91 | int32_t real_self_index = FindSelfSortIndex(message, routing_table); 92 | if (real_self_index == -1) { 93 | TOP_WARN2("real_self_index: -1 error"); 94 | //std::cout << "real_self_index: -1 error" << std::endl; 95 | return; 96 | } 97 | real_self_index = static_cast(real_self_index); 98 | //std::cout << "real_self_index:" << real_self_index <<" random_step:" << random_step << " nodes_size:" << nodes_size << " msgid:" << message.id() << std::endl; 99 | if (real_self_index <= 0 || real_self_index > nodes_size) { 100 | TOP_WARN2("real_self_index invalid, layerbroadcast failed"); 101 | return; 102 | } 103 | 104 | uint32_t logical_self_index = FindLogicalSelfIndex(real_self_index, random_step, nodes_size); 105 | //std::cout << "logically self_index:" << logical_self_index << std::endl; 106 | 107 | uint32_t neighber_count = GetNeighborCount(message); 108 | if (message.hop_num() == 0) { 109 | // meaning this is the first broadcast packet, should choose the first K nodes 110 | uint32_t min_real_index = FindRealSelfIndex(1, random_step, nodes_size) - 1; 111 | uint32_t max_real_index = FindRealSelfIndex(neighber_count, random_step, nodes_size) - 1; 112 | //std::cout << "first min_real_index:" << min_real_index << " max_real_index:" << max_real_index << std::endl; 113 | GetRangeNodes(routing_table, min_real_index, max_real_index, next_broadcast_nodes); 114 | TOP_DEBUG("the first nodes of layerbroadcast"); 115 | //std::cout << "first: next_broadcast_nodes size: " << next_broadcast_nodes.size() << std::endl; 116 | if (logical_self_index > neighber_count) { 117 | return; 118 | } 119 | } 120 | 121 | // base self_sort_index choose next nodes sort_index 122 | auto logical_result = choose_next_nodes(nodes_size, logical_self_index, neighber_count); 123 | if (logical_result.empty()) { 124 | return; 125 | } 126 | /* 127 | for (auto& item: logical_result) { 128 | std::cout << "item:" << item << "\t"; 129 | } 130 | std::cout << std::endl; 131 | */ 132 | 133 | // index start from 1 to nodes_size 134 | 135 | uint32_t real_min_index = FindRealSelfIndex(logical_result[0], random_step, nodes_size); 136 | uint32_t real_max_index = FindRealSelfIndex(logical_result[logical_result.size() - 1], random_step, nodes_size); 137 | 138 | real_min_index -= 1; 139 | real_max_index -= 1; 140 | 141 | //std::cout << "real_min_index: " << real_min_index << " real_max_index:" << real_max_index << std::endl; 142 | 143 | // attention the boundary value 144 | GetRangeNodes(routing_table, real_min_index, real_max_index, next_broadcast_nodes); 145 | //std::cout << "next_broadcast_nodes size:" << next_broadcast_nodes.size() << std::endl; 146 | return; 147 | } 148 | 149 | int32_t BroadcastLayered::FindSelfSortIndex( 150 | transport::protobuf::RoutingMessage& message, 151 | kadmlia::RoutingTablePtr& routing_table) { 152 | // start from 1 153 | int32_t index = routing_table->GetSelfIndex(); 154 | if (index == -1) { 155 | return -1; 156 | } 157 | return index + 1; 158 | } 159 | 160 | std::vector BroadcastLayered::choose_nodes( 161 | int hop_num, 162 | uint32_t self_sort_index, 163 | uint32_t neighber_count, 164 | const std::vector& sort_nodes_index_vec) { 165 | uint32_t sum1 = 0; 166 | uint32_t K = neighber_count; 167 | for (int i = 1; i < hop_num; ++i) { 168 | // max i is hop_num -1 169 | sum1 += pow(K, i); 170 | } 171 | uint32_t sum2 = sum1 + pow(K, hop_num); 172 | if (self_sort_index <= sum1 || self_sort_index > sum2) { 173 | // not right 174 | return {}; 175 | } 176 | 177 | uint32_t front_level_size = self_sort_index - sum1 - 1; 178 | uint32_t begin = sum2 + front_level_size * K + 1; 179 | uint32_t end = begin + K; 180 | std::vector result; 181 | for ( uint32_t i = begin; i < end; ++i) { 182 | if (i > sort_nodes_index_vec.size()) { 183 | break; 184 | } 185 | result.push_back(sort_nodes_index_vec[i-1]); 186 | } 187 | return result; 188 | } 189 | 190 | uint32_t BroadcastLayered::find_hop_num(uint32_t self_sort_index, uint32_t neighber_count) { 191 | uint32_t K = neighber_count; 192 | uint32_t sum1 = 0; 193 | uint32_t sum2 = 0; 194 | uint32_t hop_num = 0; 195 | for (uint32_t i = 0; ; ++i) { 196 | sum1 += pow(K, i); 197 | if (i == 0) { 198 | sum1 = 0; 199 | } 200 | sum2 = sum1 + pow(K, i+1); 201 | if (self_sort_index > sum1 && self_sort_index <= sum2) { 202 | hop_num = i + 1; 203 | break; 204 | } 205 | } 206 | return hop_num; 207 | } 208 | 209 | std::vector BroadcastLayered::choose_next_nodes( 210 | uint32_t count, 211 | uint32_t self_node_index, 212 | uint32_t neighber_count) { 213 | if (self_node_index > count) { 214 | return {}; 215 | } 216 | std::vector sort_nodes_index_vec; 217 | // 1~64 218 | for (uint32_t i = 0; i < count; ++i) { 219 | sort_nodes_index_vec.push_back(i+1); 220 | } 221 | uint32_t hop_num = find_hop_num(self_node_index, neighber_count); 222 | TOP_DEBUG("find_hop_num:%d self_index:%d", hop_num, self_node_index); 223 | //std::cout << "find_hop:" << hop_num << std::endl; 224 | 225 | auto result = choose_nodes(hop_num, self_node_index, neighber_count, sort_nodes_index_vec); 226 | return result; 227 | } 228 | 229 | 230 | } // namespace gossip 231 | 232 | } // namespace top 233 | -------------------------------------------------------------------------------- /src/block_sync_manager.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xgossip/include/block_sync_manager.h" 6 | 7 | #include "xpbase/base/top_log.h" 8 | #include "xpbase/base/kad_key/get_kadmlia_key.h" 9 | #include "xtransport/transport_message_register.h" 10 | #include "xkad/routing_table/callback_manager.h" 11 | #include "xkad/routing_table/routing_table.h" 12 | #include "xwrouter/register_routing_table.h" 13 | #include "xwrouter/message_handler/wrouter_message_handler.h" 14 | #include "xgossip/include/gossip_utils.h" 15 | #include "xutility/xhash.h" 16 | #include "xpbase/base/redis_client.h" 17 | #include "xpbase/base/top_utils.h" 18 | #include "xwrouter/xwrouter.h" 19 | 20 | namespace top { 21 | 22 | namespace gossip { 23 | 24 | static const uint32_t kMaxBlockQueueSize = 1024u; 25 | static const uint32_t kCheckHeaderHashPeriod = 1000 * 1000; // 1s 26 | static const uint32_t kSyncAskNeighborCount = 6u; // random ask 3 neighbors who has block 27 | static const uint32_t kHeaderSavePeriod = 60 * 1000; // keep 30s 28 | static const uint32_t kHeaderRequestedPeriod = 2 * 1000; // request 3s 29 | 30 | BlockSyncManager::BlockSyncManager() { 31 | wrouter::WrouterRegisterMessageHandler(kGossipBlockSyncAsk, [this]( 32 | transport::protobuf::RoutingMessage& message, 33 | base::xpacket_t& packet) { 34 | TOP_INFO("HandleMessage kGossipBlockSyncAsk"); 35 | HandleSyncAsk(message, packet); 36 | }); 37 | wrouter::WrouterRegisterMessageHandler(kGossipBlockSyncAck, [this]( 38 | transport::protobuf::RoutingMessage& message, 39 | base::xpacket_t& packet) { 40 | TOP_INFO("HandleMessage kGossipBlockSyncAck"); 41 | HandleSyncAck(message, packet); 42 | }); 43 | wrouter::WrouterRegisterMessageHandler(kGossipBlockSyncRequest, [this]( 44 | transport::protobuf::RoutingMessage& message, 45 | base::xpacket_t& packet) { 46 | TOP_INFO("HandleMessage kGossipBlockSyncRequest"); 47 | HandleSyncRequest(message, packet); 48 | }); 49 | wrouter::WrouterRegisterMessageHandler(kGossipBlockSyncResponse, [this]( 50 | transport::protobuf::RoutingMessage& message, 51 | base::xpacket_t& packet) { 52 | TOP_INFO("HandleMessage kGossipBlockSyncResponse"); 53 | HandleSyncResponse(message, packet); 54 | }); 55 | timer_.Start( 56 | kCheckHeaderHashPeriod, 57 | kCheckHeaderHashPeriod, 58 | std::bind(&BlockSyncManager::CheckHeaderHashQueue, this)); 59 | } 60 | 61 | BlockSyncManager::~BlockSyncManager() {} 62 | 63 | BlockSyncManager* BlockSyncManager::Instance() { 64 | static BlockSyncManager ins; 65 | return &ins; 66 | } 67 | 68 | void BlockSyncManager::NewBroadcastMessage(transport::protobuf::RoutingMessage& message) { 69 | if (!message.gossip().has_header_hash() || message.gossip().header_hash().empty()) { 70 | return; 71 | } 72 | TOP_DEBUG("blockmessage: msg_id(%d) has_block(%d),head_hash:%s", 73 | message.id(), 74 | message.gossip().has_block(), 75 | HexEncode(message.gossip().header_hash()).c_str()); 76 | if (DataExists(message.gossip().header_hash())) { 77 | TOP_DEBUG("blockmessage: already have"); 78 | return; 79 | } 80 | 81 | if (message.gossip().has_block() && !message.gossip().block().empty()) { 82 | TOP_DEBUG("add block message: id(%d) header_hash(%s)", 83 | message.id(), 84 | HexEncode(message.gossip().header_hash()).c_str()); 85 | header_block_data_->AddData(message.gossip().header_hash(), message.SerializeAsString()); 86 | return; 87 | } 88 | 89 | if (HeaderHashExists(message.gossip().header_hash())) { 90 | TOP_DEBUG("blockmessage header hash already have"); 91 | return; 92 | } 93 | uint64_t des_service_type; 94 | if (message.has_is_root() && message.is_root()) { 95 | des_service_type = kRoot; 96 | } else { 97 | des_service_type = GetRoutingServiceType(message.des_node_id()); 98 | } 99 | 100 | AddHeaderHashToQueue( 101 | message.gossip().header_hash(), 102 | des_service_type); 103 | 104 | } 105 | 106 | bool BlockSyncManager::DataExists(const std::string& header_hash) { 107 | return header_block_data_->HasData(header_hash); 108 | } 109 | 110 | bool BlockSyncManager::HeaderHashExists(const std::string& header_hash) { 111 | std::unique_lock lock(block_map_mutex_); 112 | auto iter = block_map_.find(header_hash); 113 | if (iter != block_map_.end()) { 114 | return true; 115 | } 116 | return false; 117 | } 118 | 119 | void BlockSyncManager::AddHeaderHashToQueue( 120 | const std::string& header_hash, 121 | uint64_t service_type) { 122 | std::unique_lock lock(block_map_mutex_); 123 | block_map_.insert(std::make_pair( 124 | header_hash, 125 | std::make_shared(SyncBlockItem{ 126 | service_type, 127 | header_hash, 128 | std::chrono::steady_clock::now() + 129 | std::chrono::milliseconds(kHeaderSavePeriod) }))); 130 | } 131 | 132 | void BlockSyncManager::SetRoutingTablePtr(kadmlia::RoutingTablePtr& routing_table) { 133 | routing_table_ = routing_table; 134 | } 135 | 136 | void BlockSyncManager::SendSyncAsk(std::shared_ptr& sync_item) { 137 | TOP_INFO("SendSyncAsk: %d, header_hash:%s",sync_item->routing_service_type,HexEncode(sync_item->header_hash).c_str()); 138 | auto routing = wrouter::GetRoutingTable(sync_item->routing_service_type); 139 | if (!routing) { 140 | TOP_INFO("no routing table:%d", sync_item->routing_service_type); 141 | return; 142 | } 143 | assert(routing); 144 | transport::protobuf::RoutingMessage pbft_message; 145 | routing->SetFreqMessage(pbft_message); 146 | pbft_message.set_type(kGossipBlockSyncAsk); 147 | pbft_message.set_id(kadmlia::CallbackManager::MessageId()); 148 | pbft_message.set_data(sync_item->header_hash); 149 | pbft_message.set_src_service_type(sync_item->routing_service_type); 150 | 151 | std::set asked_nodes; 152 | for (uint32_t i = 0; i < kSyncAskNeighborCount; ++i) { 153 | auto node_ptr = routing->GetRandomNode(); 154 | if (!node_ptr) { 155 | return; 156 | } 157 | 158 | auto iter = asked_nodes.find(node_ptr); 159 | if (iter != asked_nodes.end()) { 160 | continue; 161 | } 162 | pbft_message.set_des_node_id(node_ptr->node_id); 163 | routing->SendData(pbft_message, node_ptr->public_ip, node_ptr->public_port); 164 | TOP_DEBUG("send sync ask: %s,%d", node_ptr->public_ip.c_str(), node_ptr->public_port); 165 | } 166 | 167 | TOP_DEBUG("[gossip_sync]send out ask,%d[%s].", kGossipBlockSyncAsk, HexEncode(pbft_message.data()).c_str()); 168 | } 169 | 170 | void BlockSyncManager::CheckHeaderHashQueue() { 171 | std::map> block_map; 172 | { 173 | std::unique_lock lock(block_map_mutex_); 174 | block_map = block_map_; 175 | } 176 | 177 | auto tp_now = std::chrono::steady_clock::now(); 178 | { 179 | for (auto iter = block_map.begin(); iter != block_map.end(); ++iter) { 180 | auto item = iter->second; 181 | if (item->time_point <= tp_now || DataExists(item->header_hash)) { 182 | RemoveHeaderBlock(item->header_hash); 183 | continue; 184 | } 185 | 186 | /* 187 | if ((item->time_point - std::chrono::milliseconds(kHeaderSavePeriod) + 188 | std::chrono::milliseconds(kHeaderRequestedPeriod)) > tp_now) { 189 | continue; 190 | } 191 | */ 192 | 193 | if (HeaderHashExists(item->header_hash) && !HeaderRequested(item->header_hash)) { 194 | SendSyncAsk(item); 195 | continue; 196 | } 197 | } 198 | } 199 | } 200 | 201 | uint64_t BlockSyncManager::GetRoutingServiceType(const std::string& des_node_id) { 202 | auto kad_key = base::GetKadmliaKey(des_node_id); 203 | return kad_key->GetServiceType(); 204 | } 205 | 206 | void BlockSyncManager::SetLeagerFace(std::shared_ptr ledger_face) { 207 | header_block_data_ = std::make_shared(ledger_face); 208 | } 209 | 210 | void BlockSyncManager::HandleSyncAsk( 211 | transport::protobuf::RoutingMessage& message, 212 | base::xpacket_t& packet) { 213 | TOP_INFO("enter HandleSyncAsk:%s", HexEncode(message.data()).c_str()); 214 | if (!message.has_data()) { 215 | return; 216 | } 217 | 218 | if (message.type() != kGossipBlockSyncAsk) { 219 | return; 220 | } 221 | 222 | if (!header_block_data_->HasData(message.data())) { 223 | return; 224 | } 225 | 226 | auto routing = wrouter::GetRoutingTable(message.src_service_type()); 227 | if (!routing) { 228 | TOP_INFO("no routing table:%d", message.src_service_type()); 229 | return; 230 | } 231 | assert(routing); 232 | transport::protobuf::RoutingMessage pbft_message; 233 | routing->SetFreqMessage(pbft_message); 234 | pbft_message.set_type(kGossipBlockSyncAck); 235 | pbft_message.set_id(message.id()); 236 | pbft_message.set_data(message.data()); 237 | pbft_message.set_des_node_id(message.src_node_id()); 238 | pbft_message.set_src_service_type(message.src_service_type()); 239 | 240 | routing->SendData(pbft_message, packet.get_from_ip_addr(), packet.get_from_ip_port()); 241 | TOP_DEBUG("[gossip_sync]handled ask[%s].", HexEncode(message.data()).c_str()); 242 | } 243 | 244 | void BlockSyncManager::HandleSyncAck( 245 | transport::protobuf::RoutingMessage& message, 246 | base::xpacket_t& packet) { 247 | if (!message.has_data()) { 248 | return; 249 | } 250 | 251 | if (message.type() != kGossipBlockSyncAck) { 252 | return; 253 | } 254 | 255 | /* 256 | if (HeaderRequested(message.data())) { 257 | return; 258 | } 259 | */ 260 | 261 | if (!HeaderHashExists(message.data()) || DataExists(message.data())) { 262 | return; 263 | } 264 | 265 | auto routing = wrouter::GetRoutingTable(message.src_service_type()); 266 | if (!routing) { 267 | TOP_INFO("no routing table:%d", message.src_service_type()); 268 | return; 269 | } 270 | assert(routing); 271 | transport::protobuf::RoutingMessage pbft_message; 272 | routing->SetFreqMessage(pbft_message); 273 | pbft_message.set_type(kGossipBlockSyncRequest); 274 | pbft_message.set_id(kadmlia::CallbackManager::MessageId()); 275 | pbft_message.set_des_node_id(message.src_node_id()); 276 | pbft_message.set_data(message.data()); 277 | pbft_message.set_src_service_type(message.src_service_type()); 278 | 279 | routing->SendData(pbft_message, packet.get_from_ip_addr(), packet.get_from_ip_port()); 280 | TOP_DEBUG("[gossip_sync]handled ack[%s].", HexEncode(message.data()).c_str()); 281 | } 282 | 283 | void BlockSyncManager::HandleSyncRequest( 284 | transport::protobuf::RoutingMessage& message, 285 | base::xpacket_t& packet) { 286 | if (!message.has_data()) { 287 | return; 288 | } 289 | 290 | if (message.type() != kGossipBlockSyncRequest) { 291 | return; 292 | } 293 | 294 | std::string message_string; 295 | header_block_data_->GetData(message.data(), message_string); 296 | if (message_string.empty()) { 297 | return; 298 | } 299 | 300 | auto routing = wrouter::GetRoutingTable(message.src_service_type()); 301 | if (!routing) { 302 | TOP_INFO("no routing table:%d", message.src_service_type()); 303 | return; 304 | } 305 | assert(routing); 306 | transport::protobuf::RoutingMessage pbft_message; 307 | routing->SetFreqMessage(pbft_message); 308 | pbft_message.set_type(kGossipBlockSyncResponse); 309 | pbft_message.set_id(message.id()); 310 | pbft_message.set_des_node_id(message.src_node_id()); 311 | transport::protobuf::GossipSyncBlockData gossip_data; 312 | gossip_data.set_header_hash(message.data()); 313 | gossip_data.set_block(message_string); // get the whole message stored 314 | pbft_message.set_data(gossip_data.SerializeAsString()); 315 | pbft_message.set_src_service_type(message.src_service_type()); 316 | 317 | routing->SendData(pbft_message, packet.get_from_ip_addr(), packet.get_from_ip_port()); 318 | TOP_DEBUG("[gossip_sync]handled request[%s].", HexEncode(message.data()).c_str()); 319 | } 320 | 321 | void BlockSyncManager::HandleSyncResponse( 322 | transport::protobuf::RoutingMessage& message, 323 | base::xpacket_t& packet) { 324 | if (!message.has_data()) { 325 | return; 326 | } 327 | 328 | if (message.type() != kGossipBlockSyncResponse) { 329 | return; 330 | } 331 | 332 | transport::protobuf::GossipSyncBlockData gossip_data; 333 | if (!gossip_data.ParseFromString(message.data())) { 334 | return; 335 | } 336 | std::string header_hash = gossip_data.header_hash(); 337 | 338 | if (!HeaderHashExists(header_hash)) { 339 | return; 340 | } 341 | if (header_block_data_->HasData(header_hash)){ 342 | return; 343 | } 344 | 345 | transport::protobuf::RoutingMessage sync_message; 346 | if (!sync_message.ParseFromString(gossip_data.block())) { 347 | TOP_WARN("SyncMessae ParseFromString failed"); 348 | return; 349 | } 350 | header_block_data_->AddData(header_hash, gossip_data.block()); 351 | 352 | // call callback 353 | if (sync_message.type() == kElectVhostRumorMessage) { 354 | std::string vhost_data = sync_message.gossip().block(); 355 | uint32_t vhash = base::xhash32_t::digest(vhost_data); 356 | if (header_hash != std::to_string(vhash)) { 357 | TOP_WARN("[gossip_sync] header hash(%s) not equal", HexEncode(header_hash).c_str()); 358 | return; 359 | } 360 | base::xpacket_t packet; 361 | wrouter::Wrouter::Instance()->HandleOwnSyncPacket(sync_message, packet); 362 | TOP_DEBUG("blockmessage callback hash:%u,header_hash:%s,type:%d", vhash, HexEncode(header_hash).c_str(), sync_message.type()); 363 | } else if (sync_message.type() == kTestChainTrade) { 364 | #ifndef NDEBUG 365 | std::string vhost_data = sync_message.gossip().block(); 366 | uint32_t vhash = base::xhash32_t::digest(vhost_data); 367 | if (header_hash != std::to_string(vhash)) { 368 | TOP_WARN("[gossip_sync] header hash(%s) not equal", HexEncode(header_hash).c_str()); 369 | return; 370 | } 371 | base::xpacket_t packet; 372 | wrouter::Wrouter::Instance()->HandleOwnSyncPacket(sync_message, packet); 373 | TOP_DEBUG("blockmessage callback msg_hash:%u,header_hash:%s,type:%d", sync_message.gossip().msg_hash(), HexEncode(header_hash).c_str(), sync_message.type()); 374 | std::cout << "sync block ok " << std::endl; 375 | #endif 376 | } 377 | 378 | RemoveHeaderBlock(header_hash); 379 | TOP_DEBUG("blockmessage add block data size(%d),hash:%s", gossip_data.block().size(), HexEncode(header_hash).c_str()); 380 | } 381 | 382 | void BlockSyncManager::RemoveHeaderBlock(const std::string& header_hash) { 383 | { 384 | std::unique_lock lock(requested_headers_mutex_); 385 | auto iter = requested_headers_.find(header_hash); 386 | if (iter != requested_headers_.end()) { 387 | requested_headers_.erase(iter); 388 | } 389 | } 390 | 391 | { 392 | std::unique_lock lock(block_map_mutex_); 393 | auto iter = block_map_.find(header_hash); 394 | if (iter != block_map_.end()) { 395 | block_map_.erase(iter); 396 | } 397 | } 398 | // (delete block from db) 399 | header_block_data_->RemoveData(header_hash); 400 | } 401 | 402 | bool BlockSyncManager::HeaderRequested(const std::string& header_hash) { 403 | auto tp_now = std::chrono::steady_clock::now(); 404 | std::unique_lock lock(requested_headers_mutex_); 405 | auto iter = requested_headers_.find(header_hash); 406 | if (iter != requested_headers_.end()) { 407 | if (iter->second <= tp_now) { 408 | requested_headers_.erase(iter); 409 | return false; 410 | } 411 | // in kHeaderRequestPeriod seconds, have requested 412 | return true; 413 | } 414 | 415 | requested_headers_.insert(std::make_pair( 416 | header_hash, 417 | std::chrono::steady_clock::now() + 418 | std::chrono::milliseconds(kHeaderRequestedPeriod))); 419 | return false; 420 | } 421 | 422 | } // namespace gossip 423 | 424 | } // namespace top 425 | -------------------------------------------------------------------------------- /xgossip.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 99FA79D722B273A000B5D6BE /* gossip_interface.h in Headers */ = {isa = PBXBuildFile; fileRef = 99FA79C522B273A000B5D6BE /* gossip_interface.h */; }; 11 | 99FA79D822B273A000B5D6BE /* block_sync_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = 99FA79C722B273A000B5D6BE /* block_sync_manager.h */; }; 12 | 99FA79D922B273A000B5D6BE /* broadcast_layered.h in Headers */ = {isa = PBXBuildFile; fileRef = 99FA79C822B273A000B5D6BE /* broadcast_layered.h */; }; 13 | 99FA79DA22B273A000B5D6BE /* gossip_bloomfilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 99FA79C922B273A000B5D6BE /* gossip_bloomfilter.h */; }; 14 | 99FA79DB22B273A000B5D6BE /* gossip_bloomfilter_layer.h in Headers */ = {isa = PBXBuildFile; fileRef = 99FA79CA22B273A000B5D6BE /* gossip_bloomfilter_layer.h */; }; 15 | 99FA79DC22B273A000B5D6BE /* gossip_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 99FA79CB22B273A000B5D6BE /* gossip_utils.h */; }; 16 | 99FA79DD22B273A000B5D6BE /* header_block_data.h in Headers */ = {isa = PBXBuildFile; fileRef = 99FA79CC22B273A000B5D6BE /* header_block_data.h */; }; 17 | 99FA79DE22B273A000B5D6BE /* mesages_with_bloomfilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 99FA79CD22B273A000B5D6BE /* mesages_with_bloomfilter.h */; }; 18 | 99FA79DF22B273A000B5D6BE /* random_layered_broadcast.h in Headers */ = {isa = PBXBuildFile; fileRef = 99FA79CE22B273A000B5D6BE /* random_layered_broadcast.h */; }; 19 | 99FA79E022B273A000B5D6BE /* block_sync_manager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 99FA79D022B273A000B5D6BE /* block_sync_manager.cc */; }; 20 | 99FA79E122B273A000B5D6BE /* broadcast_layered.cc in Sources */ = {isa = PBXBuildFile; fileRef = 99FA79D122B273A000B5D6BE /* broadcast_layered.cc */; }; 21 | 99FA79E222B273A000B5D6BE /* gossip_bloomfilter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 99FA79D222B273A000B5D6BE /* gossip_bloomfilter.cc */; }; 22 | 99FA79E322B273A000B5D6BE /* gossip_bloomfilter_layer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 99FA79D322B273A000B5D6BE /* gossip_bloomfilter_layer.cc */; }; 23 | 99FA79E422B273A000B5D6BE /* gossip_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 99FA79D422B273A000B5D6BE /* gossip_utils.cc */; }; 24 | 99FA79E522B273A000B5D6BE /* header_block_data.cc in Sources */ = {isa = PBXBuildFile; fileRef = 99FA79D522B273A000B5D6BE /* header_block_data.cc */; }; 25 | 99FA79E622B273A000B5D6BE /* messages_with_bloomfilter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 99FA79D622B273A000B5D6BE /* messages_with_bloomfilter.cc */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 99FA788B22B2719D00B5D6BE /* libxgossip.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libxgossip.a; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 99FA79C522B273A000B5D6BE /* gossip_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gossip_interface.h; sourceTree = ""; }; 31 | 99FA79C722B273A000B5D6BE /* block_sync_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = block_sync_manager.h; sourceTree = ""; }; 32 | 99FA79C822B273A000B5D6BE /* broadcast_layered.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = broadcast_layered.h; sourceTree = ""; }; 33 | 99FA79C922B273A000B5D6BE /* gossip_bloomfilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gossip_bloomfilter.h; sourceTree = ""; }; 34 | 99FA79CA22B273A000B5D6BE /* gossip_bloomfilter_layer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gossip_bloomfilter_layer.h; sourceTree = ""; }; 35 | 99FA79CB22B273A000B5D6BE /* gossip_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gossip_utils.h; sourceTree = ""; }; 36 | 99FA79CC22B273A000B5D6BE /* header_block_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = header_block_data.h; sourceTree = ""; }; 37 | 99FA79CD22B273A000B5D6BE /* mesages_with_bloomfilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mesages_with_bloomfilter.h; sourceTree = ""; }; 38 | 99FA79CE22B273A000B5D6BE /* random_layered_broadcast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = random_layered_broadcast.h; sourceTree = ""; }; 39 | 99FA79D022B273A000B5D6BE /* block_sync_manager.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = block_sync_manager.cc; sourceTree = ""; }; 40 | 99FA79D122B273A000B5D6BE /* broadcast_layered.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = broadcast_layered.cc; sourceTree = ""; }; 41 | 99FA79D222B273A000B5D6BE /* gossip_bloomfilter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gossip_bloomfilter.cc; sourceTree = ""; }; 42 | 99FA79D322B273A000B5D6BE /* gossip_bloomfilter_layer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gossip_bloomfilter_layer.cc; sourceTree = ""; }; 43 | 99FA79D422B273A000B5D6BE /* gossip_utils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gossip_utils.cc; sourceTree = ""; }; 44 | 99FA79D522B273A000B5D6BE /* header_block_data.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = header_block_data.cc; sourceTree = ""; }; 45 | 99FA79D622B273A000B5D6BE /* messages_with_bloomfilter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = messages_with_bloomfilter.cc; sourceTree = ""; }; 46 | /* End PBXFileReference section */ 47 | 48 | /* Begin PBXFrameworksBuildPhase section */ 49 | 99FA788822B2719D00B5D6BE /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | ); 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | /* End PBXFrameworksBuildPhase section */ 57 | 58 | /* Begin PBXGroup section */ 59 | 99FA788222B2719D00B5D6BE = { 60 | isa = PBXGroup; 61 | children = ( 62 | 99FA79C422B2739500B5D6BE /* source */, 63 | 99FA788C22B2719D00B5D6BE /* Products */, 64 | ); 65 | sourceTree = ""; 66 | }; 67 | 99FA788C22B2719D00B5D6BE /* Products */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 99FA788B22B2719D00B5D6BE /* libxgossip.a */, 71 | ); 72 | name = Products; 73 | sourceTree = ""; 74 | }; 75 | 99FA79C422B2739500B5D6BE /* source */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 99FA79C522B273A000B5D6BE /* gossip_interface.h */, 79 | 99FA79C622B273A000B5D6BE /* include */, 80 | 99FA79CF22B273A000B5D6BE /* src */, 81 | ); 82 | name = source; 83 | sourceTree = ""; 84 | }; 85 | 99FA79C622B273A000B5D6BE /* include */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 99FA79C722B273A000B5D6BE /* block_sync_manager.h */, 89 | 99FA79C822B273A000B5D6BE /* broadcast_layered.h */, 90 | 99FA79C922B273A000B5D6BE /* gossip_bloomfilter.h */, 91 | 99FA79CA22B273A000B5D6BE /* gossip_bloomfilter_layer.h */, 92 | 99FA79CB22B273A000B5D6BE /* gossip_utils.h */, 93 | 99FA79CC22B273A000B5D6BE /* header_block_data.h */, 94 | 99FA79CD22B273A000B5D6BE /* mesages_with_bloomfilter.h */, 95 | 99FA79CE22B273A000B5D6BE /* random_layered_broadcast.h */, 96 | ); 97 | path = include; 98 | sourceTree = ""; 99 | }; 100 | 99FA79CF22B273A000B5D6BE /* src */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 99FA79D022B273A000B5D6BE /* block_sync_manager.cc */, 104 | 99FA79D122B273A000B5D6BE /* broadcast_layered.cc */, 105 | 99FA79D222B273A000B5D6BE /* gossip_bloomfilter.cc */, 106 | 99FA79D322B273A000B5D6BE /* gossip_bloomfilter_layer.cc */, 107 | 99FA79D422B273A000B5D6BE /* gossip_utils.cc */, 108 | 99FA79D522B273A000B5D6BE /* header_block_data.cc */, 109 | 99FA79D622B273A000B5D6BE /* messages_with_bloomfilter.cc */, 110 | ); 111 | path = src; 112 | sourceTree = ""; 113 | }; 114 | /* End PBXGroup section */ 115 | 116 | /* Begin PBXHeadersBuildPhase section */ 117 | 99FA788922B2719D00B5D6BE /* Headers */ = { 118 | isa = PBXHeadersBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | 99FA79D722B273A000B5D6BE /* gossip_interface.h in Headers */, 122 | 99FA79DC22B273A000B5D6BE /* gossip_utils.h in Headers */, 123 | 99FA79DA22B273A000B5D6BE /* gossip_bloomfilter.h in Headers */, 124 | 99FA79DF22B273A000B5D6BE /* random_layered_broadcast.h in Headers */, 125 | 99FA79DB22B273A000B5D6BE /* gossip_bloomfilter_layer.h in Headers */, 126 | 99FA79DD22B273A000B5D6BE /* header_block_data.h in Headers */, 127 | 99FA79D822B273A000B5D6BE /* block_sync_manager.h in Headers */, 128 | 99FA79DE22B273A000B5D6BE /* mesages_with_bloomfilter.h in Headers */, 129 | 99FA79D922B273A000B5D6BE /* broadcast_layered.h in Headers */, 130 | ); 131 | runOnlyForDeploymentPostprocessing = 0; 132 | }; 133 | /* End PBXHeadersBuildPhase section */ 134 | 135 | /* Begin PBXNativeTarget section */ 136 | 99FA788A22B2719D00B5D6BE /* xgossip */ = { 137 | isa = PBXNativeTarget; 138 | buildConfigurationList = 99FA788F22B2719D00B5D6BE /* Build configuration list for PBXNativeTarget "xgossip" */; 139 | buildPhases = ( 140 | 99FA788722B2719D00B5D6BE /* Sources */, 141 | 99FA788822B2719D00B5D6BE /* Frameworks */, 142 | 99FA788922B2719D00B5D6BE /* Headers */, 143 | ); 144 | buildRules = ( 145 | ); 146 | dependencies = ( 147 | ); 148 | name = xgossip; 149 | productName = xgossip; 150 | productReference = 99FA788B22B2719D00B5D6BE /* libxgossip.a */; 151 | productType = "com.apple.product-type.library.static"; 152 | }; 153 | /* End PBXNativeTarget section */ 154 | 155 | /* Begin PBXProject section */ 156 | 99FA788322B2719D00B5D6BE /* Project object */ = { 157 | isa = PBXProject; 158 | attributes = { 159 | LastUpgradeCheck = 0830; 160 | ORGANIZATIONNAME = "Taylor Wei"; 161 | TargetAttributes = { 162 | 99FA788A22B2719D00B5D6BE = { 163 | CreatedOnToolsVersion = 8.3.2; 164 | ProvisioningStyle = Automatic; 165 | }; 166 | }; 167 | }; 168 | buildConfigurationList = 99FA788622B2719D00B5D6BE /* Build configuration list for PBXProject "xgossip" */; 169 | compatibilityVersion = "Xcode 3.2"; 170 | developmentRegion = English; 171 | hasScannedForEncodings = 0; 172 | knownRegions = ( 173 | en, 174 | ); 175 | mainGroup = 99FA788222B2719D00B5D6BE; 176 | productRefGroup = 99FA788C22B2719D00B5D6BE /* Products */; 177 | projectDirPath = ""; 178 | projectRoot = ""; 179 | targets = ( 180 | 99FA788A22B2719D00B5D6BE /* xgossip */, 181 | ); 182 | }; 183 | /* End PBXProject section */ 184 | 185 | /* Begin PBXSourcesBuildPhase section */ 186 | 99FA788722B2719D00B5D6BE /* Sources */ = { 187 | isa = PBXSourcesBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | 99FA79E622B273A000B5D6BE /* messages_with_bloomfilter.cc in Sources */, 191 | 99FA79E122B273A000B5D6BE /* broadcast_layered.cc in Sources */, 192 | 99FA79E422B273A000B5D6BE /* gossip_utils.cc in Sources */, 193 | 99FA79E222B273A000B5D6BE /* gossip_bloomfilter.cc in Sources */, 194 | 99FA79E322B273A000B5D6BE /* gossip_bloomfilter_layer.cc in Sources */, 195 | 99FA79E522B273A000B5D6BE /* header_block_data.cc in Sources */, 196 | 99FA79E022B273A000B5D6BE /* block_sync_manager.cc in Sources */, 197 | ); 198 | runOnlyForDeploymentPostprocessing = 0; 199 | }; 200 | /* End PBXSourcesBuildPhase section */ 201 | 202 | /* Begin XCBuildConfiguration section */ 203 | 99FA788D22B2719D00B5D6BE /* Debug */ = { 204 | isa = XCBuildConfiguration; 205 | buildSettings = { 206 | ALWAYS_SEARCH_USER_PATHS = NO; 207 | CLANG_ANALYZER_NONNULL = YES; 208 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 209 | CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; 210 | CLANG_CXX_LIBRARY = "libc++"; 211 | CLANG_ENABLE_MODULES = YES; 212 | CLANG_ENABLE_OBJC_ARC = YES; 213 | CLANG_WARN_BOOL_CONVERSION = YES; 214 | CLANG_WARN_CONSTANT_CONVERSION = YES; 215 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 216 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 217 | CLANG_WARN_EMPTY_BODY = YES; 218 | CLANG_WARN_ENUM_CONVERSION = YES; 219 | CLANG_WARN_INFINITE_RECURSION = YES; 220 | CLANG_WARN_INT_CONVERSION = YES; 221 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 222 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 223 | CLANG_WARN_UNREACHABLE_CODE = YES; 224 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 225 | CODE_SIGN_IDENTITY = "-"; 226 | COPY_PHASE_STRIP = NO; 227 | DEBUG_INFORMATION_FORMAT = dwarf; 228 | ENABLE_STRICT_OBJC_MSGSEND = YES; 229 | ENABLE_TESTABILITY = YES; 230 | GCC_C_LANGUAGE_STANDARD = c99; 231 | GCC_DYNAMIC_NO_PIC = NO; 232 | GCC_NO_COMMON_BLOCKS = YES; 233 | GCC_OPTIMIZATION_LEVEL = 0; 234 | GCC_PREPROCESSOR_DEFINITIONS = ( 235 | "DEBUG=1", 236 | "$(inherited)", 237 | ); 238 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 239 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 240 | GCC_WARN_UNDECLARED_SELECTOR = YES; 241 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 242 | GCC_WARN_UNUSED_FUNCTION = YES; 243 | GCC_WARN_UNUSED_VARIABLE = YES; 244 | HEADER_SEARCH_PATHS = ../xdepends/include; 245 | MACOSX_DEPLOYMENT_TARGET = 10.12; 246 | MTL_ENABLE_DEBUG_INFO = YES; 247 | ONLY_ACTIVE_ARCH = YES; 248 | SDKROOT = macosx; 249 | USER_HEADER_SEARCH_PATHS = "../ ../xdepends/include ../third_party"; 250 | }; 251 | name = Debug; 252 | }; 253 | 99FA788E22B2719D00B5D6BE /* Release */ = { 254 | isa = XCBuildConfiguration; 255 | buildSettings = { 256 | ALWAYS_SEARCH_USER_PATHS = NO; 257 | CLANG_ANALYZER_NONNULL = YES; 258 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 259 | CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; 260 | CLANG_CXX_LIBRARY = "libc++"; 261 | CLANG_ENABLE_MODULES = YES; 262 | CLANG_ENABLE_OBJC_ARC = YES; 263 | CLANG_WARN_BOOL_CONVERSION = YES; 264 | CLANG_WARN_CONSTANT_CONVERSION = YES; 265 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 266 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 267 | CLANG_WARN_EMPTY_BODY = YES; 268 | CLANG_WARN_ENUM_CONVERSION = YES; 269 | CLANG_WARN_INFINITE_RECURSION = YES; 270 | CLANG_WARN_INT_CONVERSION = YES; 271 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 272 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 273 | CLANG_WARN_UNREACHABLE_CODE = YES; 274 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 275 | CODE_SIGN_IDENTITY = "-"; 276 | COPY_PHASE_STRIP = NO; 277 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 278 | ENABLE_NS_ASSERTIONS = NO; 279 | ENABLE_STRICT_OBJC_MSGSEND = YES; 280 | GCC_C_LANGUAGE_STANDARD = c99; 281 | GCC_NO_COMMON_BLOCKS = YES; 282 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 283 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 284 | GCC_WARN_UNDECLARED_SELECTOR = YES; 285 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 286 | GCC_WARN_UNUSED_FUNCTION = YES; 287 | GCC_WARN_UNUSED_VARIABLE = YES; 288 | HEADER_SEARCH_PATHS = ../xdepends/include; 289 | MACOSX_DEPLOYMENT_TARGET = 10.12; 290 | MTL_ENABLE_DEBUG_INFO = NO; 291 | SDKROOT = macosx; 292 | USER_HEADER_SEARCH_PATHS = "../ ../xdepends/include ../third_party"; 293 | }; 294 | name = Release; 295 | }; 296 | 99FA789022B2719D00B5D6BE /* Debug */ = { 297 | isa = XCBuildConfiguration; 298 | buildSettings = { 299 | EXECUTABLE_PREFIX = lib; 300 | PRODUCT_NAME = "$(TARGET_NAME)"; 301 | }; 302 | name = Debug; 303 | }; 304 | 99FA789122B2719D00B5D6BE /* Release */ = { 305 | isa = XCBuildConfiguration; 306 | buildSettings = { 307 | EXECUTABLE_PREFIX = lib; 308 | PRODUCT_NAME = "$(TARGET_NAME)"; 309 | }; 310 | name = Release; 311 | }; 312 | /* End XCBuildConfiguration section */ 313 | 314 | /* Begin XCConfigurationList section */ 315 | 99FA788622B2719D00B5D6BE /* Build configuration list for PBXProject "xgossip" */ = { 316 | isa = XCConfigurationList; 317 | buildConfigurations = ( 318 | 99FA788D22B2719D00B5D6BE /* Debug */, 319 | 99FA788E22B2719D00B5D6BE /* Release */, 320 | ); 321 | defaultConfigurationIsVisible = 0; 322 | defaultConfigurationName = Release; 323 | }; 324 | 99FA788F22B2719D00B5D6BE /* Build configuration list for PBXNativeTarget "xgossip" */ = { 325 | isa = XCConfigurationList; 326 | buildConfigurations = ( 327 | 99FA789022B2719D00B5D6BE /* Debug */, 328 | 99FA789122B2719D00B5D6BE /* Release */, 329 | ); 330 | defaultConfigurationIsVisible = 0; 331 | defaultConfigurationName = Release; 332 | }; 333 | /* End XCConfigurationList section */ 334 | }; 335 | rootObject = 99FA788322B2719D00B5D6BE /* Project object */; 336 | } 337 | -------------------------------------------------------------------------------- /src/gossip_interface.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2019 Telos Foundation & contributors 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #include "xgossip/gossip_interface.h" 6 | 7 | #include 8 | 9 | #include "xpbase/base/top_log.h" 10 | #include "xpbase/base/uint64_bloomfilter.h" 11 | #include "xgossip/include/gossip_utils.h" 12 | 13 | namespace top { 14 | 15 | namespace gossip { 16 | 17 | // TODO(Charlie): for test evil 18 | bool GossipInterface::ThisNodeIsEvil(transport::protobuf::RoutingMessage& message) { 19 | if (message.gossip().evil_rate() <= 0) { 20 | TOP_DEBUG("gossip evil_rate(%d) not work", message.gossip().evil_rate()); 21 | return false; 22 | } 23 | TOP_INFO("gossip evil_rate(%d) work", message.gossip().evil_rate()); 24 | 25 | static uint32_t all_node_num = 0; 26 | if (all_node_num == 0) { 27 | static std::mutex tmp_mutex; 28 | std::unique_lock lock(tmp_mutex); 29 | if (all_node_num == 0) { 30 | uint32_t hash_num = base::xhash32_t::digest(global_xid->Get()); 31 | srand(hash_num); 32 | int32_t rand_num = rand() % 10000; 33 | if (rand_num <= (message.gossip().evil_rate() * 1000)) { 34 | all_node_num = 1; 35 | } else { 36 | all_node_num = 2; 37 | } 38 | } 39 | } 40 | return all_node_num == 1; 41 | } 42 | 43 | void GossipInterface::CheckDiffNetwork(transport::protobuf::RoutingMessage& message) { 44 | if (message.gossip().diff_net()) { 45 | auto gossip_param = message.mutable_gossip(); 46 | gossip_param->set_diff_net(false); 47 | message.clear_bloomfilter(); 48 | message.set_hop_num(0); 49 | TOP_INFO("message from diff network and arrive the des network at the first time. %s", 50 | message.debug().c_str()); 51 | } 52 | } 53 | 54 | uint64_t GossipInterface::GetDistance(const std::string& src, const std::string& des) { 55 | assert(src.size() >= sizeof(uint64_t)); 56 | assert(des.size() >= sizeof(uint64_t)); 57 | assert(src.size() == des.size()); 58 | uint64_t dis = 0; 59 | uint32_t index = src.size() - 1; 60 | uint32_t rollleft_num = 56; 61 | for (uint32_t i = 0; i < 8; ++i) { 62 | dis += (static_cast(static_cast(src[index]) ^ 63 | static_cast(des[index])) << rollleft_num); 64 | --index; 65 | rollleft_num -= 8; 66 | } 67 | return dis; 68 | } 69 | 70 | void GossipInterface::Send( 71 | transport::protobuf::RoutingMessage& message, 72 | const std::vector& nodes) { 73 | std::string body; 74 | if (!message.SerializeToString(&body)) { 75 | TOP_WARN2("wrouter message SerializeToString failed"); 76 | return; 77 | } 78 | _xip2_header xip2_header; 79 | memset(&xip2_header, 0, sizeof(xip2_header)); 80 | std::string header((const char*)&xip2_header, sizeof(xip2_header)); 81 | std::string xdata = header + body; 82 | base::xpacket_t packet( 83 | base::xcontext_t::instance(), 84 | (uint8_t*)xdata.c_str(), 85 | xdata.size(), 86 | 0,0, 87 | false); 88 | auto each_call = [this, &message, &packet, &xdata] (kadmlia::NodeInfoPtr node_info_ptr) { 89 | // TODO(Charlie): just for test, delete it 90 | if (!node_info_ptr) { 91 | TOP_WARN2("kadmlia::NodeInfoPtr null"); 92 | return false; 93 | } 94 | 95 | if (node_info_ptr->xid.empty()) { 96 | TOP_ERROR("node xid is empty."); 97 | return false; 98 | } 99 | if ((node_info_ptr->xid).compare(global_xid->Get()) == 0) { 100 | TOP_ERROR("node xid equal self."); 101 | return false; 102 | } 103 | 104 | packet.reset(); 105 | packet.get_body().push_back((uint8_t*)xdata.data(), xdata.size()); 106 | packet.set_to_ip_addr(node_info_ptr->public_ip); 107 | packet.set_to_ip_port(node_info_ptr->public_port); 108 | 109 | if (kadmlia::kKadSuccess != transport_ptr_->SendData(packet)) { 110 | TOP_WARN2("SendData to endpoint(%s:%d) failed", 111 | node_info_ptr->public_ip.c_str(), 112 | node_info_ptr->public_port); 113 | return false; 114 | } 115 | #ifdef TOP_TESTING_PERFORMANCE 116 | TOP_DEBUG("SendData size(%d) to endpoint(%s:%d) success", 117 | packet.get_body().size(), 118 | node_info_ptr->public_ip.c_str(), 119 | node_info_ptr->public_port); 120 | TOP_NETWORK_DEBUG_FOR_PROTOMESSAGE( 121 | std::string("send to: ") + 122 | node_info_ptr->public_ip + ":" + 123 | check_cast(node_info_ptr->public_port), 124 | message); 125 | #endif 126 | return true; 127 | }; 128 | 129 | std::for_each(nodes.begin(), nodes.end(), each_call); 130 | } 131 | 132 | uint32_t GossipInterface::GetNeighborCount(transport::protobuf::RoutingMessage& message) { 133 | if (message.gossip().neighber_count() > 0) { 134 | return message.gossip().neighber_count(); 135 | } 136 | 137 | if (message.gossip().reliable_level() > 0) { 138 | return GetRandomNeighbersCount(message.gossip().reliable_level()); 139 | } 140 | return GetRandomNeighbersCount(kGossipReliableLow); 141 | } 142 | 143 | std::vector GossipInterface::GetRandomNodes( 144 | std::vector& neighbors, 145 | uint32_t number_to_get) const { 146 | if (neighbors.size() <= number_to_get) { 147 | return neighbors; 148 | } 149 | std::random_shuffle(neighbors.begin(), neighbors.end()); 150 | return std::vector { 151 | neighbors.begin(), 152 | neighbors.begin() + number_to_get}; 153 | } 154 | 155 | void GossipInterface::SelectNodes( 156 | transport::protobuf::RoutingMessage& message, 157 | const std::vector& nodes, 158 | std::vector& select_nodes) { 159 | uint64_t min_dis = message.gossip().min_dis(); 160 | uint64_t max_dis = message.gossip().max_dis(); 161 | if (max_dis <= 0) { 162 | max_dis = std::numeric_limits::max(); 163 | } 164 | uint64_t left_min = message.gossip().left_min(); 165 | uint64_t right_max = message.gossip().right_max(); 166 | uint32_t left_overlap = message.gossip().left_overlap(); 167 | uint32_t right_overlap = message.gossip().right_overlap(); 168 | if (left_overlap > 0 && left_overlap < 20) { 169 | uint64_t tmp_min_dis = min_dis; 170 | double rate = (double)left_overlap / 10; 171 | uint64_t step = static_cast((tmp_min_dis - left_min) * rate); 172 | if (step > tmp_min_dis) { 173 | min_dis = 0; 174 | } else { 175 | min_dis = tmp_min_dis - step; 176 | } 177 | } 178 | if (right_overlap > 0 && right_overlap < 20) { 179 | uint64_t tmp_max_dis = max_dis; 180 | double rate = (double)right_overlap / 10; 181 | uint64_t step = static_cast((right_max - max_dis) * rate); 182 | if (std::numeric_limits::max() - step > tmp_max_dis) { 183 | max_dis = tmp_max_dis + step; 184 | } else { 185 | max_dis = std::numeric_limits::max(); 186 | } 187 | } 188 | 189 | uint32_t select_num = GetNeighborCount(message); 190 | for (auto iter = nodes.begin(); iter != nodes.end(); ++iter) { 191 | if (select_nodes.size() >= select_num) { 192 | break; 193 | } 194 | 195 | if ((*iter)->hash64 > min_dis && (*iter)->hash64 < max_dis) { 196 | select_nodes.push_back(*iter); 197 | } 198 | } 199 | 200 | std::sort( 201 | select_nodes.begin(), 202 | select_nodes.end(), 203 | [](const kadmlia::NodeInfoPtr& left, const kadmlia::NodeInfoPtr& right) -> bool{ 204 | return left->hash64 < right->hash64; 205 | }); 206 | } 207 | 208 | void GossipInterface::SelectNodes( 209 | transport::protobuf::RoutingMessage& message, 210 | kadmlia::RoutingTablePtr& routing_table, 211 | std::shared_ptr& bloomfilter, 212 | std::vector& select_nodes) { 213 | uint64_t min_dis = message.gossip().min_dis(); 214 | uint64_t max_dis = message.gossip().max_dis(); 215 | if (max_dis <= 0) { 216 | max_dis = std::numeric_limits::max(); 217 | } 218 | uint64_t left_min = message.gossip().left_min(); 219 | uint64_t right_max = message.gossip().right_max(); 220 | uint32_t left_overlap = message.gossip().left_overlap(); 221 | uint32_t right_overlap = message.gossip().right_overlap(); 222 | if (left_overlap > 0 && left_overlap < 20) { 223 | uint64_t tmp_min_dis = min_dis; 224 | double rate = (double)left_overlap / 10; 225 | uint64_t step = static_cast((tmp_min_dis - left_min) * rate); 226 | if (step > tmp_min_dis) { 227 | min_dis = 0; 228 | } else { 229 | min_dis = tmp_min_dis - step; 230 | } 231 | } 232 | if (right_overlap > 0 && right_overlap < 20) { 233 | uint64_t tmp_max_dis = max_dis; 234 | double rate = (double)right_overlap / 10; 235 | uint64_t step = static_cast((right_max - max_dis) * rate); 236 | if (std::numeric_limits::max() - step > tmp_max_dis) { 237 | max_dis = tmp_max_dis + step; 238 | } else { 239 | max_dis = std::numeric_limits::max(); 240 | } 241 | } 242 | 243 | uint32_t select_num = GetNeighborCount(message); 244 | std::vector nodes; 245 | routing_table->GetRangeNodes(min_dis, max_dis, nodes); 246 | if (nodes.empty()) { 247 | return; 248 | } 249 | 250 | // uint32_t filtered = 0; 251 | auto gossip_param = message.mutable_gossip(); 252 | std::random_shuffle(nodes.begin(), nodes.end()); 253 | for (auto iter = nodes.begin(); iter != nodes.end(); ++iter) { 254 | if (select_nodes.size() >= select_num) { 255 | break; 256 | } 257 | if (!IsIpValid((*iter)->public_ip)) { 258 | continue; 259 | } 260 | if ((*iter)->hash64 == 0) { 261 | continue; 262 | } 263 | if (((*iter)->xid).compare(global_xid->Get()) == 0) { 264 | continue; 265 | } 266 | 267 | if (bloomfilter->Contain((*iter)->hash64)) { 268 | #ifdef TOP_TESTING_PERFORMANCE 269 | ++filtered; 270 | TOP_NETWORK_DEBUG_FOR_PROTOMESSAGE( 271 | std::string("message filterd: ") + (*iter)->public_ip + 272 | ":" + std::to_string((*iter)->public_port), message); 273 | #endif 274 | continue; 275 | } 276 | 277 | if ((*iter)->public_ip == gossip_param->pre_ip() && 278 | (*iter)->public_port == gossip_param->pre_port()) { 279 | if (message.hop_num() > message.gossip().ign_bloomfilter_level()) { 280 | bloomfilter->Add((*iter)->hash64); 281 | } 282 | continue; 283 | } 284 | select_nodes.push_back(*iter); 285 | } 286 | gossip_param->clear_pre_ip(); 287 | gossip_param->clear_pre_port(); 288 | 289 | std::sort( 290 | select_nodes.begin(), 291 | select_nodes.end(), 292 | [](const kadmlia::NodeInfoPtr& left, const kadmlia::NodeInfoPtr& right) -> bool{ 293 | return left->hash64 < right->hash64; 294 | }); 295 | } 296 | 297 | void GossipInterface::SendLayered( 298 | transport::protobuf::RoutingMessage& message, 299 | const std::vector& nodes) { 300 | uint64_t min_dis = message.gossip().min_dis(); 301 | uint64_t max_dis = message.gossip().max_dis(); 302 | if (max_dis <= 0) { 303 | max_dis = std::numeric_limits::max(); 304 | } 305 | 306 | uint8_t local_buf[kUdpPacketBufferSize]; 307 | base::xpacket_t packet(base::xcontext_t::instance(), local_buf, sizeof(local_buf), 0, false); 308 | _xip2_header xip2_header; 309 | memset(&xip2_header, 0, sizeof(xip2_header)); 310 | std::string header((const char*)&xip2_header, sizeof(xip2_header)); 311 | std::string xdata; 312 | 313 | for (uint32_t i = 0; i < nodes.size(); ++i) { 314 | auto gossip = message.mutable_gossip(); 315 | if (i == 0) { 316 | gossip->set_min_dis(min_dis); 317 | gossip->set_left_min(min_dis); 318 | 319 | if (nodes.size() == 1) { 320 | gossip->set_max_dis(max_dis); 321 | gossip->set_right_max(max_dis); 322 | } else { 323 | gossip->set_max_dis(nodes[0]->hash64); 324 | gossip->set_right_max(nodes[1]->hash64); 325 | } 326 | } 327 | 328 | if (i > 0 && i < (nodes.size() - 1)) { 329 | gossip->set_min_dis(nodes[i - 1]->hash64); 330 | gossip->set_max_dis(nodes[i]->hash64); 331 | 332 | if (i == 1) { 333 | gossip->set_left_min(min_dis); 334 | } else { 335 | gossip->set_left_min(nodes[i - 2]->hash64); 336 | } 337 | gossip->set_right_max(nodes[i + 1]->hash64); 338 | } 339 | 340 | if (i > 0 && i == (nodes.size() - 1)) { 341 | gossip->set_min_dis(nodes[i - 1]->hash64); 342 | gossip->set_max_dis(max_dis); 343 | 344 | if (i == 1) { 345 | gossip->set_left_min(min_dis); 346 | } else { 347 | gossip->set_left_min(nodes[i - 2]->hash64); 348 | } 349 | gossip->set_right_max(max_dis); 350 | } 351 | 352 | std::string body; 353 | if (!message.SerializeToString(&body)) { 354 | TOP_WARN2("wrouter message SerializeToString failed"); 355 | return; 356 | } 357 | xdata = header + body; 358 | packet.reset(); 359 | packet.get_body().push_back((uint8_t*)xdata.data(), xdata.size()); 360 | packet.set_to_ip_addr(nodes[i]->public_ip); 361 | packet.set_to_ip_port(nodes[i]->public_port); 362 | 363 | if (kadmlia::kKadSuccess != transport_ptr_->SendData(packet)) { 364 | TOP_WARN2("SendData to endpoint(%s:%d) failed", 365 | nodes[i]->public_ip.c_str(), 366 | nodes[i]->public_port); 367 | continue; 368 | } 369 | #ifdef TOP_TESTING_PERFORMANCE 370 | TOP_NETWORK_DEBUG_FOR_PROTOMESSAGE( 371 | std::string("send to: ") + 372 | nodes[i]->public_ip + ":" + 373 | check_cast(nodes[i]->public_port), 374 | message); 375 | #endif 376 | }; 377 | } 378 | 379 | #define OUT_NETWORK_IPS 380 | #ifdef OUT_NETWORK_IPS 381 | static const std::unordered_set test_for_valid_ip_set{ 382 | "104.248.176.228", 383 | "104.248.176.48", 384 | "104.248.176.8", 385 | 386 | "104.248.178.100", 387 | "104.248.178.119", 388 | "104.248.178.123", 389 | 390 | "104.248.178.135", 391 | "104.248.178.148", 392 | "104.248.178.182", 393 | 394 | "104.248.178.186", 395 | "104.248.178.193", 396 | "104.248.178.194", 397 | 398 | "104.248.178.3", 399 | "104.248.178.64", 400 | "104.248.178.99", 401 | 402 | "104.248.180.196", 403 | "104.248.180.199", 404 | "104.248.180.24", 405 | 406 | "104.248.180.242", 407 | "104.248.180.246", 408 | "104.248.180.38", 409 | 410 | "104.248.180.52", 411 | "104.248.180.72", 412 | "104.248.180.74", 413 | 414 | "104.248.180.98", 415 | "104.248.180.99", 416 | "104.248.184.0" 417 | }; 418 | #else 419 | static const std::unordered_set test_for_valid_ip_set{ 420 | "192.168.50.81", 421 | "192.168.50.82", 422 | "192.168.50.84", 423 | 424 | "192.168.50.85", 425 | "192.168.50.86", 426 | "192.168.50.91", 427 | 428 | "192.168.50.92", 429 | "192.168.50.94", 430 | "192.168.50.95", 431 | 432 | "192.168.50.96", 433 | "192.168.50.97", 434 | "192.168.50.98", 435 | 436 | "192.168.50.99", 437 | "192.168.50.100", 438 | "192.168.50.101", 439 | 440 | "192.168.50.102", 441 | "192.168.50.104", 442 | "192.168.50.105" 443 | }; 444 | #endif 445 | 446 | bool GossipInterface::IsIpValid(const std::string& ip) { 447 | #ifdef TOP_TESTING_PERFORMANCE_IP_TEST 448 | return test_for_valid_ip_set.find(ip) != test_for_valid_ip_set.end(); 449 | #else 450 | return true; 451 | #endif 452 | } 453 | 454 | } // namespace gossip 455 | 456 | } // namespace top 457 | --------------------------------------------------------------------------------