From 37948bdc7b8989ce71dc46e78a70e23b81685167 Mon Sep 17 00:00:00 2001 From: Steven Siloti Date: Tue, 1 Aug 2017 11:25:11 -0700 Subject: [PATCH] remove support for BEP 30 merkle tree torrents With the adoption of BEP 52, BEP 30 is now obsolete. This code has also been broken for some time. The merkle_* functions have been retained because they will probably be usefull for BEP 52. --- examples/make_torrent.cpp | 16 -- include/libtorrent/add_torrent_params.hpp | 10 +- include/libtorrent/create_torrent.hpp | 20 +-- include/libtorrent/settings_pack.hpp | 8 +- include/libtorrent/torrent.hpp | 2 - include/libtorrent/torrent_info.hpp | 50 ++++-- src/bt_peer_connection.cpp | 149 +----------------- src/create_torrent.cpp | 52 +----- src/read_resume_data.cpp | 8 - src/session_handle.cpp | 2 - src/settings_pack.cpp | 2 +- src/torrent.cpp | 36 ----- src/torrent_info.cpp | 125 ++------------- src/write_resume_data.cpp | 10 -- test/test_torrent_info.cpp | 7 - test/test_torrents/invalid_merkle.torrent | 1 - test/test_torrents/invalid_root_hash.torrent | 1 - test/test_torrents/invalid_root_hash2.torrent | 1 - test/test_torrents/root_hash.torrent | 1 - 19 files changed, 83 insertions(+), 418 deletions(-) delete mode 100644 test/test_torrents/invalid_merkle.torrent delete mode 100644 test/test_torrents/invalid_root_hash.torrent delete mode 100644 test/test_torrents/invalid_root_hash2.torrent delete mode 100644 test/test_torrents/root_hash.torrent diff --git a/examples/make_torrent.cpp b/examples/make_torrent.cpp index 37fbd15272e..dab3c440ded 100644 --- a/examples/make_torrent.cpp +++ b/examples/make_torrent.cpp @@ -117,10 +117,6 @@ or directory and writes it to standard out OPTIONS: --m file generate a merkle hash tree torrent. - merkle torrents require client support - the resulting full merkle tree is written to - the specified file -w url adds a web seed to the torrent with the specified url -t url adds the specified tracker to the @@ -173,7 +169,6 @@ int main(int argc_, char const* argv_[]) try std::string root_cert; std::string outfile; - std::string merklefile; #ifdef TORRENT_WINDOWS // don't ever write binary data to the console on windows // it will just be interpreted as text and corrupted @@ -221,10 +216,6 @@ int main(int argc_, char const* argv_[]) try pad_file_limit = atoi(args[1]); flags |= lt::create_torrent::optimize_alignment; break; - case 'm': - merklefile = args[1]; - flags |= lt::create_torrent::merkle; - break; case 'S': { if (strlen(args[1]) != 40) { std::cerr << "invalid info-hash for -S. " @@ -331,13 +322,6 @@ int main(int argc_, char const* argv_[]) try std::cout.write(torrent.data(), torrent.size()); } - if (!merklefile.empty()) { - std::fstream merkle; - merkle.exceptions(std::ifstream::failbit); - merkle.open(merklefile.c_str(), std::ios_base::out | std::ios_base::binary); - auto const& tree = t.merkle_tree(); - merkle.write(reinterpret_cast(tree.data()), tree.size() * 20); - } return 0; } catch (std::exception& e) { diff --git a/include/libtorrent/add_torrent_params.hpp b/include/libtorrent/add_torrent_params.hpp index 460f3a2088b..9c123814f46 100644 --- a/include/libtorrent/add_torrent_params.hpp +++ b/include/libtorrent/add_torrent_params.hpp @@ -312,10 +312,18 @@ TORRENT_VERSION_NAMESPACE_2 // precedence. aux::noexcept_movable> piece_priorities; +#if TORRENT_ABI_VERSION <= 2 + // support for BEP 30 merkle torrents has been removed + // if this is a merkle tree torrent, and you're seeding, this field must // be set. It is all the hashes in the binary tree, with the root as the // first entry. See torrent_info::set_merkle_tree() for more info. - aux::noexcept_movable> merkle_tree; + aux::noexcept_movable> TORRENT_DEPRECATED_MEMBER merkle_tree; +#else + // hidden + // to maintain ABI compatibility + aux::noexcept_movable> deprecated6; +#endif // this is a map of file indices in the torrent and new filenames to be // applied before the torrent is added. diff --git a/include/libtorrent/create_torrent.hpp b/include/libtorrent/create_torrent.hpp index 83ca9ed08fc..2822ecc73c7 100644 --- a/include/libtorrent/create_torrent.hpp +++ b/include/libtorrent/create_torrent.hpp @@ -119,7 +119,10 @@ namespace libtorrent { // When creating merkle torrents, the full hash tree is also generated // and should be saved off separately. It is accessed through the // create_torrent::merkle_tree() function. - static constexpr create_flags_t merkle = 1_bit; +#ifndef TORRENT_NO_DEPRECATE + // support for BEP 30 merkle torrents has been removed + static constexpr create_flags_t TORRENT_DEPRECATED_MEMBER merkle = 1_bit; +#endif // This will include the file modification time as part of the torrent. // This is not enabled by default, as it might cause problems when you @@ -272,13 +275,18 @@ namespace libtorrent { int piece_length() const { return m_files.piece_length(); } int piece_size(piece_index_t i) const { return m_files.piece_size(i); } +#ifndef TORRENT_NO_DEPRECATE + // support for BEP 30 merkle torrents has been removed + // This function returns the merkle hash tree, if the torrent was created as a merkle // torrent. The tree is created by ``generate()`` and won't be valid until that function // has been called. When creating a merkle tree torrent, the actual tree itself has to // be saved off separately and fed into libtorrent the first time you start seeding it, // through the ``torrent_info::set_merkle_tree()`` function. From that point onwards, the // tree will be saved in the resume data. - std::vector const& merkle_tree() const { return m_merkle_tree; } + TORRENT_DEPRECATED + std::vector merkle_tree() const { return std::vector(); } +#endif // Add similar torrents (by info-hash) or collections of similar torrents. // Similar torrents are expected to share some files with this torrent. @@ -312,11 +320,6 @@ namespace libtorrent { std::vector m_similar; std::vector m_collections; - // if we're generating a merkle torrent, this is the - // merkle tree we got. This should be saved in fast-resume - // in order to start seeding the torrent - mutable aux::vector m_merkle_tree; - // dht nodes to add to the routing table/bootstrap from std::vector> m_nodes; @@ -347,9 +350,6 @@ namespace libtorrent { // advertise itself on the DHT for this torrent bool m_private:1; - // if set to one, a merkle torrent will be generated - bool m_merkle_torrent:1; - // if set, include the 'mtime' modification time in the // torrent file bool m_include_mtime:1; diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index d5d1f153f77..41092f38787 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -642,9 +642,15 @@ namespace aux { // if false, prevents libtorrent to advertise share-mode support support_share_mode, +#if TORRENT_ABI_VERSION <= 2 + // support for BEP 30 merkle torrents has been removed + // if this is false, don't advertise support for the Tribler merkle // tree piece message - support_merkle_torrents, + support_merkle_torrents TORRENT_DEPRECATED_ENUM, +#else + deprecated_support_merkle_torrents, +#endif // if this is true, the number of redundant bytes is sent to the // tracker diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index d4ccfaf1087..9390d3d2323 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -1067,8 +1067,6 @@ namespace libtorrent { { return m_verified.get_bit(piece); } void verified(piece_index_t piece); - bool add_merkle_nodes(std::map const& n, piece_index_t piece); - // this is called once periodically for torrents // that are not private void lsd_announce(); diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp index e5e2c54e4ee..b9820b8df0a 100644 --- a/include/libtorrent/torrent_info.hpp +++ b/include/libtorrent/torrent_info.hpp @@ -458,22 +458,17 @@ namespace libtorrent { TORRENT_ASSERT(index < m_files.end_piece()); TORRENT_ASSERT(is_loaded()); int const idx = static_cast(index); - if (is_merkle_torrent()) - { - TORRENT_ASSERT(idx < m_merkle_tree.end_index() - m_merkle_first_leaf); - return m_merkle_tree[m_merkle_first_leaf + idx].data(); - } - else - { - TORRENT_ASSERT(m_piece_hashes); - TORRENT_ASSERT(m_piece_hashes >= m_info_section.get()); - TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size); - TORRENT_ASSERT(idx < int(m_info_section_size / 20)); - return &m_piece_hashes[idx * 20]; - } + TORRENT_ASSERT(m_piece_hashes); + TORRENT_ASSERT(m_piece_hashes >= m_info_section.get()); + TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size); + TORRENT_ASSERT(idx < int(m_info_section_size / 20)); + return &m_piece_hashes[idx * 20]; } - bool is_loaded() const { return m_piece_hashes || !m_merkle_tree.empty(); } + bool is_loaded() const { return m_piece_hashes; } + +#if TORRENT_ABI_VERSION <= 2 + // support for BEP 30 merkle torrents has been removed // ``merkle_tree()`` returns a reference to the merkle tree for this // torrent, if any. @@ -484,9 +479,12 @@ namespace libtorrent { // ``create_torrent::merkle_tree()`` function, and need to be saved // separately from the torrent file itself. Once it's added to // libtorrent, the merkle tree will be persisted in the resume data. + TORRENT_DEPRECATED std::vector const& merkle_tree() const { return m_merkle_tree; } + TORRENT_DEPRECATED void set_merkle_tree(std::vector& h) { TORRENT_ASSERT(h.size() == m_merkle_tree.size() ); m_merkle_tree.swap(h); } +#endif // ``name()`` returns the name of the torrent. // name contains UTF-8 encoded string. @@ -541,16 +539,26 @@ namespace libtorrent { boost::shared_array metadata() const { return m_info_section; } +#if TORRENT_ABI_VERSION <= 2 + // support for BEP 30 merkle torrents has been removed + // internal - bool add_merkle_nodes(std::map const& subtree - , piece_index_t piece); - std::map build_merkle_list(piece_index_t piece) const; + TORRENT_DEPRECATED + bool add_merkle_nodes(std::map const& + , piece_index_t) { return false; } + TORRENT_DEPRECATED + std::map build_merkle_list(piece_index_t) const + { + return std::map(); + } // returns whether or not this is a merkle torrent. // see `BEP 30`__. // // __ http://bittorrent.org/beps/bep_0030.html + TORRENT_DEPRECATED bool is_merkle_torrent() const { return !m_merkle_tree.empty(); } +#endif bool parse_torrent_file(bdecode_node const& libtorrent, error_code& ec); @@ -608,10 +616,14 @@ namespace libtorrent { // cannot be pointers into that buffer. std::vector m_owned_collections; +#if TORRENT_ABI_VERSION <= 2 // if this is a merkle torrent, this is the merkle // tree. It has space for merkle_num_nodes(merkle_num_leafs(num_pieces)) // hashes aux::vector m_merkle_tree; +#else + aux::vector deprecated1; +#endif // this is a copy of the info section from the torrent. // it use maintained in this flat format in order to @@ -646,9 +658,13 @@ namespace libtorrent { // the number of bytes in m_info_section std::int32_t m_info_section_size = 0; +#if TORRENT_ABI_VERSION <= 2 // the index to the first leaf. This is where the hash for the // first piece is stored std::int32_t m_merkle_first_leaf = 0; +#else + std::int32_t deprecated2 = 0; +#endif enum flags_t : std::uint8_t { diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index 739fada41bb..281543f1113 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -728,12 +728,6 @@ namespace { // we support extensions *(ptr + 5) |= 0x10; - if (m_settings.get_bool(settings_pack::support_merkle_torrents)) - { - // we support merkle torrents - *(ptr + 5) |= 0x08; - } - // we support FAST extension *(ptr + 7) |= 0x04; @@ -1034,79 +1028,29 @@ namespace { std::shared_ptr t = associated_torrent().lock(); TORRENT_ASSERT(t); - bool const merkle = static_cast(recv_buffer.front()) == 250; - if (merkle) + if (recv_pos == 1) { - if (recv_pos == 1) - { - received_bytes(0, received); - return; - } - if (recv_pos < 13) - { - received_bytes(0, received); - return; - } - char const* ptr = recv_buffer.data() + 9; - int const list_size = detail::read_int32(ptr); - - if (list_size > m_recv_buffer.packet_size() - 13 || list_size < 0) - { - received_bytes(0, received); - disconnect(errors::invalid_hash_list, operation_t::bittorrent, peer_error); - return; - } - - if (m_recv_buffer.packet_size() - 13 - list_size > t->block_size()) + if (m_recv_buffer.packet_size() - 9 > t->block_size()) { received_bytes(0, received); disconnect(errors::packet_too_large, operation_t::bittorrent, peer_error); return; } } - else - { - if (recv_pos == 1) - { - if (m_recv_buffer.packet_size() - 9 > t->block_size()) - { - received_bytes(0, received); - disconnect(errors::packet_too_large, operation_t::bittorrent, peer_error); - return; - } - } - } // classify the received data as protocol chatter // or data payload for the statistics int piece_bytes = 0; - int header_size = merkle?13:9; + int const header_size = 9; peer_request p; - int list_size = 0; if (recv_pos >= header_size) { const char* ptr = recv_buffer.data() + 1; p.piece = piece_index_t(detail::read_int32(ptr)); p.start = detail::read_int32(ptr); - - if (merkle) - { - list_size = detail::read_int32(ptr); - if (list_size < 0) - { - received_bytes(0, received); - disconnect(errors::invalid_hash_list, operation_t::bittorrent, peer_error); - return; - } - p.length = m_recv_buffer.packet_size() - list_size - header_size; - header_size += list_size; - } - else - { - p.length = m_recv_buffer.packet_size() - header_size; - } + p.length = m_recv_buffer.packet_size() - header_size; } else { @@ -1156,49 +1100,6 @@ namespace { incoming_piece_fragment(piece_bytes); if (!m_recv_buffer.packet_finished()) return; - if (merkle && list_size > 0) - { -#ifndef TORRENT_DISABLE_LOGGING - peer_log(peer_log_alert::incoming_message, "HASHPIECE" - , "piece: %d list: %d", static_cast(p.piece), list_size); -#endif - error_code ec; - bdecode_node const hash_list = bdecode(recv_buffer.subspan(13).first(list_size) - , ec); - if (ec) - { - disconnect(errors::invalid_hash_piece, operation_t::bittorrent, peer_error); - return; - } - - // the list has this format: - // [ [node-index, hash], [node-index, hash], ... ] - if (hash_list.type() != bdecode_node::list_t) - { - disconnect(errors::invalid_hash_list, operation_t::bittorrent, peer_error); - return; - } - - std::map nodes; - for (int i = 0; i < hash_list.list_size(); ++i) - { - bdecode_node const e = hash_list.list_at(i); - if (e.type() != bdecode_node::list_t - || e.list_size() != 2 - || e.list_at(0).type() != bdecode_node::int_t - || e.list_at(1).type() != bdecode_node::string_t - || e.list_at(1).string_length() != 20) continue; - - nodes.emplace(int(e.list_int_value_at(0)) - , sha1_hash(e.list_at(1).string_ptr())); - } - if (!nodes.empty() && !t->add_merkle_nodes(nodes, p.piece)) - { - disconnect(errors::invalid_hash_piece, operation_t::bittorrent, peer_error); - return; - } - } - incoming_piece(p, recv_buffer.data() + header_size); } @@ -1833,10 +1734,7 @@ namespace { span recv_buffer = m_recv_buffer.get(); TORRENT_ASSERT(int(recv_buffer.size()) >= 1); - int packet_type = static_cast(recv_buffer[0]); - - if (m_settings.get_bool(settings_pack::support_merkle_torrents) - && packet_type == 250) packet_type = msg_piece; + int const packet_type = static_cast(recv_buffer[0]); #if TORRENT_USE_ASSERTS std::int64_t const cur_payload_dl = statistics().last_payload_downloaded(); @@ -2325,7 +2223,6 @@ namespace { std::shared_ptr t = associated_torrent().lock(); TORRENT_ASSERT(t); - bool merkle = t->torrent_file().is_merkle_torrent() && r.start == 0; // the hash piece looks like this: // uint8_t msg // uint32_t piece index @@ -2337,43 +2234,11 @@ namespace { char* ptr = msg; TORRENT_ASSERT(r.length <= 16 * 1024); detail::write_int32(r.length + 1 + 4 + 4, ptr); - if (m_settings.get_bool(settings_pack::support_merkle_torrents) && merkle) - detail::write_uint8(250, ptr); - else - detail::write_uint8(msg_piece, ptr); + detail::write_uint8(msg_piece, ptr); detail::write_int32(static_cast(r.piece), ptr); detail::write_int32(r.start, ptr); - // if this is a merkle torrent and the start offset - // is 0, we need to include the merkle node hashes - if (merkle) - { - std::vector piece_list_buf; - entry piece_list; - entry::list_type& l = piece_list.list(); - std::map merkle_node_list = t->torrent_file().build_merkle_list(r.piece); - l.reserve(merkle_node_list.size()); - for (auto const& i : merkle_node_list) - { - l.emplace_back(entry::list_t); - l.back().list().emplace_back(i.first); - l.back().list().emplace_back(i.second.to_string()); - } - bencode(std::back_inserter(piece_list_buf), piece_list); - detail::write_int32(int(piece_list_buf.size()), ptr); - - // back-patch the length field - char* ptr2 = msg; - detail::write_int32(r.length + 1 + 4 + 4 + 4 + int(piece_list_buf.size()) - , ptr2); - - send_buffer({msg, 17}); - send_buffer(piece_list_buf); - } - else - { - send_buffer({msg, 13}); - } + send_buffer({msg, 13}); if (buffer.is_mutable()) { diff --git a/src/create_torrent.cpp b/src/create_torrent.cpp index 62009ed19cf..6889bfe0f23 100644 --- a/src/create_torrent.cpp +++ b/src/create_torrent.cpp @@ -54,8 +54,8 @@ namespace libtorrent { constexpr create_flags_t create_torrent::optimize_alignment; #if TORRENT_ABI_VERSION == 1 constexpr create_flags_t create_torrent::optimize; -#endif constexpr create_flags_t create_torrent::merkle; +#endif constexpr create_flags_t create_torrent::modification_time; constexpr create_flags_t create_torrent::symlinks; constexpr create_flags_t create_torrent::mutable_torrent_support; @@ -347,7 +347,6 @@ namespace { , m_creation_date(::time(nullptr)) , m_multifile(fs.num_files() > 1) , m_private(false) - , m_merkle_torrent(bool(flags & create_torrent::merkle)) , m_include_mtime(bool(flags & create_torrent::modification_time)) , m_include_symlinks(bool(flags & create_torrent::symlinks)) { @@ -358,7 +357,7 @@ namespace { m_multifile = true; // a piece_size of 0 means automatic - if (piece_size == 0 && !m_merkle_torrent) + if (piece_size == 0) { // size_table is computed from the following: // target_list_size = sqrt(total_size) * 2; @@ -385,10 +384,6 @@ namespace { } piece_size = default_block_size << i; } - else if (piece_size == 0 && m_merkle_torrent) - { - piece_size = 64*1024; - } // to support mutable torrents, alignment always has to be the piece size, // because piece hashes are compared to determine whether files are @@ -414,7 +409,6 @@ namespace { , m_creation_date(::time(nullptr)) , m_multifile(ti.num_files() > 1) , m_private(ti.priv()) - , m_merkle_torrent(ti.is_merkle_torrent()) , m_include_mtime(false) , m_include_symlinks(false) { @@ -653,45 +647,11 @@ namespace { } info["piece length"] = m_files.piece_length(); - if (m_merkle_torrent) - { - int const num_leafs = merkle_num_leafs(m_files.num_pieces()); - int const num_nodes = merkle_num_nodes(num_leafs); - int const first_leaf = num_nodes - num_leafs; - m_merkle_tree.resize(num_nodes); - auto const num_pieces = int(m_piece_hash.size()); - for (int i = 0; i < num_pieces; ++i) - m_merkle_tree[first_leaf + i] = m_piece_hash[piece_index_t(i)]; - for (int i = num_pieces; i < num_leafs; ++i) - m_merkle_tree[first_leaf + i].clear(); - - // now that we have initialized all leaves, build - // each level bottom-up - int level_start = first_leaf; - int level_size = num_leafs; - while (level_start > 0) - { - int parent = merkle_get_parent(level_start); - for (int i = level_start; i < level_start + level_size; i += 2, ++parent) - { - hasher h; - h.update(m_merkle_tree[i]); - h.update(m_merkle_tree[i + 1]); - m_merkle_tree[parent] = h.final(); - } - level_start = merkle_get_parent(level_start); - level_size /= 2; - } - TORRENT_ASSERT(level_size == 1); - info["root hash"] = m_merkle_tree[0]; - } - else - { - std::string& p = info["pieces"].string(); - for (sha1_hash const& h : m_piece_hash) - p.append(h.data(), h.size()); - } + std::string& p = info["pieces"].string(); + + for (sha1_hash const& h : m_piece_hash) + p.append(h.data(), h.size()); return dict; } diff --git a/src/read_resume_data.cpp b/src/read_resume_data.cpp index 5a45936fea9..4044ac4d558 100644 --- a/src/read_resume_data.cpp +++ b/src/read_resume_data.cpp @@ -251,14 +251,6 @@ namespace { } } - bdecode_node const mt = rd.dict_find_string("merkle tree"); - if (mt && mt.string_length() >= int(sha1_hash::size())) - { - ret.merkle_tree.resize(aux::numeric_cast(mt.string_length()) / sha1_hash::size()); - std::memcpy(ret.merkle_tree.data(), mt.string_ptr() - , ret.merkle_tree.size() * sha1_hash::size()); - } - // some sanity checking. Maybe we shouldn't be in seed mode anymore if (bdecode_node const pieces = rd.dict_find_string("pieces")) { diff --git a/src/session_handle.cpp b/src/session_handle.cpp index d3ed00a26e3..f007d0a7a5e 100644 --- a/src/session_handle.cpp +++ b/src/session_handle.cpp @@ -327,8 +327,6 @@ namespace { atp.verified_pieces.swap(resume_data.verified_pieces); atp.piece_priorities.swap(resume_data.piece_priorities); - atp.merkle_tree = std::move(resume_data.merkle_tree); - atp.renamed_files = std::move(resume_data.renamed_files); if (!(atp.flags & add_torrent_params::flag_override_resume_data)) diff --git a/src/settings_pack.cpp b/src/settings_pack.cpp index ec02e30eab9..4d2f1f0f031 100644 --- a/src/settings_pack.cpp +++ b/src/settings_pack.cpp @@ -183,7 +183,7 @@ constexpr int CLOSE_FILE_INTERVAL = 0; SET(allow_partial_disk_writes, true, nullptr), DEPRECATED_SET(force_proxy, false, nullptr), SET(support_share_mode, true, nullptr), - SET(support_merkle_torrents, true, nullptr), + DEPRECATED_SET(support_merkle_torrents, false, nullptr), SET(report_redundant_bytes, true, nullptr), SET(listen_system_port_fallback, true, nullptr), DEPRECATED_SET(use_disk_cache_pool, false, nullptr), diff --git a/src/torrent.cpp b/src/torrent.cpp index 2b9ffee5657..22076e3d02f 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -308,29 +308,6 @@ bool is_downloading_state(int const st) if (settings().get_bool(settings_pack::prefer_udp_trackers)) prioritize_udp_trackers(); - // --- MERKLE TREE --- - - if (m_torrent_file->is_valid() - && m_torrent_file->is_merkle_torrent()) - { - if (p.merkle_tree.size() == m_torrent_file->merkle_tree().size()) - { - // TODO: 2 set_merkle_tree should probably take the vector as && - std::vector tree(p.merkle_tree); - m_torrent_file->set_merkle_tree(tree); - } - else - { - // TODO: 0 if this is a merkle torrent and we can't - // restore the tree, we need to wipe all the - // bits in the have array, but not necessarily - // we might want to do a full check to see if we have - // all the pieces. This is low priority since almost - // no one uses merkle torrents - TORRENT_ASSERT_FAIL(); - } - } - if (m_torrent_file->is_valid()) { // setting file- or piece priorities for seed mode makes no sense. If a @@ -1211,12 +1188,6 @@ bool is_downloading_state(int const st) } catch (...) { handle_exception(); } - bool torrent::add_merkle_nodes(std::map const& nodes - , piece_index_t const piece) - { - return m_torrent_file->add_merkle_nodes(nodes, piece); - } - peer_request torrent::to_req(piece_block const& p) const { int block_offset = p.block_index * block_size(); @@ -5907,13 +5878,6 @@ bool is_downloading_state(int const st) } } - if (m_torrent_file->is_merkle_torrent()) - { - // we need to save the whole merkle hash tree - // in order to resume - ret.merkle_tree = m_torrent_file->merkle_tree(); - } - // if this torrent is a seed, we won't have a piece picker // if we don't have anything, we may also not have a picker // in either case; there will be no half-finished pieces. diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index c00508a6bdc..cee218ced19 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -572,14 +572,12 @@ namespace { , m_urls(t.m_urls) , m_web_seeds(t.m_web_seeds) , m_nodes(t.m_nodes) - , m_merkle_tree(t.m_merkle_tree) , m_piece_hashes(t.m_piece_hashes) , m_comment(t.m_comment) , m_created_by(t.m_created_by) , m_creation_date(t.m_creation_date) , m_info_hash(t.m_info_hash) , m_info_section_size(t.m_info_section_size) - , m_merkle_first_leaf(t.m_merkle_first_leaf) , m_flags(t.m_flags) { #if TORRENT_USE_INVARIANT_CHECKS @@ -980,9 +978,7 @@ namespace { swap(m_info_section, ti.m_info_section); swap(m_piece_hashes, ti.m_piece_hashes); m_info_dict.swap(ti.m_info_dict); - swap(m_merkle_tree, ti.m_merkle_tree); swap(m_info_section_size, ti.m_info_section_size); - swap(m_merkle_first_leaf, ti.m_merkle_first_leaf); swap(m_flags, ti.m_flags); } @@ -1120,8 +1116,7 @@ namespace { / files.piece_length())); bdecode_node const pieces = info.dict_find_string("pieces"); - bdecode_node const root_hash = info.dict_find_string("root hash"); - if (!pieces && !root_hash) + if (!pieces) { ec = errors::torrent_missing_pieces; // mark the torrent as invalid @@ -1145,44 +1140,18 @@ namespace { return false; } - if (pieces) + if (pieces.string_length() != files.num_pieces() * 20) { - if (pieces.string_length() != files.num_pieces() * 20) - { - ec = errors::torrent_invalid_hashes; - // mark the torrent as invalid - m_files.set_piece_length(0); - return false; - } - - m_piece_hashes = pieces.string_ptr() + info_ptr_diff; - TORRENT_ASSERT(m_piece_hashes >= m_info_section.get()); - TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size); - } - else - { - TORRENT_ASSERT(root_hash); - if (root_hash.string_length() != 20) - { - ec = errors::torrent_invalid_hashes; - // mark the torrent as invalid - m_files.set_piece_length(0); - return false; - } - if (files.num_pieces() <= 0) - { - ec = errors::no_files_in_torrent; - // mark the torrent as invalid - m_files.set_piece_length(0); - return false; - } - int const num_leafs = merkle_num_leafs(files.num_pieces()); - int const num_nodes = merkle_num_nodes(num_leafs); - m_merkle_first_leaf = num_nodes - num_leafs; - m_merkle_tree.resize(num_nodes); - m_merkle_tree[0].assign(root_hash.string_ptr()); + ec = errors::torrent_invalid_hashes; + // mark the torrent as invalid + m_files.set_piece_length(0); + return false; } + m_piece_hashes = pieces.string_ptr() + info_ptr_diff; + TORRENT_ASSERT(m_piece_hashes >= m_info_section.get()); + TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size); + m_flags |= (info.dict_find_int_value("private", 0) != 0) ? private_torrent : 0; @@ -1239,80 +1208,6 @@ namespace { return m_info_dict.dict_find(key); } - - bool torrent_info::add_merkle_nodes(std::map const& subtree - , piece_index_t const piece) - { - INVARIANT_CHECK; - - int n = m_merkle_first_leaf + static_cast(piece); - auto const it = subtree.find(n); - if (it == subtree.end()) return false; - sha1_hash h = it->second; - - // if the verification passes, these are the - // nodes to add to our tree - std::map to_add; - - while (n > 0) - { - int const sibling = merkle_get_sibling(n); - int const parent = merkle_get_parent(n); - auto const sibling_hash = subtree.find(sibling); - if (sibling_hash == subtree.end()) - return false; - to_add[n] = h; - to_add[sibling] = sibling_hash->second; - hasher hs; - if (sibling < n) - { - hs.update(sibling_hash->second); - hs.update(h); - } - else - { - hs.update(h); - hs.update(sibling_hash->second); - } - h = hs.final(); - n = parent; - } - if (h != m_merkle_tree[0]) return false; - - // the nodes and piece hash matched the root-hash - // insert them into our tree - - for (auto const& i : to_add) - { - m_merkle_tree[i.first] = i.second; - } - return true; - } - - // builds a list of nodes that are required to verify - // the given piece - std::map - torrent_info::build_merkle_list(piece_index_t const piece) const - { - INVARIANT_CHECK; - - std::map ret; - int n = m_merkle_first_leaf + static_cast(piece); - ret[n] = m_merkle_tree[n]; - ret[0] = m_merkle_tree[0]; - while (n > 0) - { - int sibling = merkle_get_sibling(n); - int parent = merkle_get_parent(n); - ret[sibling] = m_merkle_tree[sibling]; - // we cannot build the tree path if one - // of the nodes in the tree is missing - TORRENT_ASSERT(!m_merkle_tree[sibling].is_all_zeros()); - n = parent; - } - return ret; - } - bool torrent_info::parse_torrent_file(bdecode_node const& torrent_file , error_code& ec) { diff --git a/src/write_resume_data.cpp b/src/write_resume_data.cpp index b7ff90694a2..67b54503357 100644 --- a/src/write_resume_data.cpp +++ b/src/write_resume_data.cpp @@ -93,16 +93,6 @@ namespace libtorrent { ret["info"].preformatted().assign(&info[0], &info[0] + size); } - if (!atp.merkle_tree.empty()) - { - // we need to save the whole merkle hash tree - // in order to resume - std::string& tree_str = ret["merkle tree"].string(); - auto const& tree = atp.merkle_tree; - tree_str.resize(tree.size() * 20); - std::memcpy(&tree_str[0], &tree[0], tree.size() * 20); - } - if (!atp.unfinished_pieces.empty()) { entry::list_type& up = ret["unfinished"].list(); diff --git a/test/test_torrent_info.cpp b/test/test_torrent_info.cpp index 741fa33f57b..7d403d411f9 100644 --- a/test/test_torrent_info.cpp +++ b/test/test_torrent_info.cpp @@ -120,7 +120,6 @@ static test_torrent_t test_torrents[] = { "url_seed_multi_single_file.torrent" }, { "url_seed_multi_space.torrent" }, { "url_seed_multi_space_nolist.torrent" }, - { "root_hash.torrent" }, { "empty_path_multi.torrent" }, { "duplicate_web_seeds.torrent" }, { "invalid_name2.torrent" }, @@ -158,9 +157,6 @@ test_failing_torrent_t test_error_torrents[] = { "missing_path_list.torrent", errors::torrent_missing_name }, { "invalid_pieces.torrent", errors::torrent_missing_pieces }, { "unaligned_pieces.torrent", errors::torrent_invalid_hashes }, - { "invalid_root_hash.torrent", errors::torrent_invalid_hashes }, - { "invalid_root_hash2.torrent", errors::torrent_missing_pieces }, - { "invalid_merkle.torrent", errors::no_files_in_torrent}, { "invalid_file_size.torrent", errors::torrent_invalid_length }, { "invalid_symlink.torrent", errors::torrent_invalid_name }, { "many_pieces.torrent", errors::too_many_pieces_in_torrent }, @@ -170,17 +166,14 @@ test_failing_torrent_t test_error_torrents[] = } // anonymous namespace // TODO: test remap_files -// TODO: merkle torrents. specifically torrent_info::add_merkle_nodes and torrent with "root hash" // TODO: torrent with 'p' (padfile) attribute // TODO: torrent with 'h' (hidden) attribute // TODO: torrent with 'x' (executable) attribute // TODO: torrent with 'l' (symlink) attribute -// TODO: creating a merkle torrent (torrent_info::build_merkle_list) // TODO: torrent with multiple trackers in multiple tiers, making sure we // shuffle them (how do you test shuffling?, load it multiple times and make // sure it's in different order at least once) // TODO: torrents with a zero-length name -// TODO: torrents with a merkle tree and add_merkle_nodes // TODO: torrent with a non-dictionary info-section // TODO: torrents with DHT nodes // TODO: torrent with url-list as a single string diff --git a/test/test_torrents/invalid_merkle.torrent b/test/test_torrents/invalid_merkle.torrent deleted file mode 100644 index ec555de9d24..00000000000 --- a/test/test_torrents/invalid_merkle.torrent +++ /dev/null @@ -1 +0,0 @@ -d10:cion datei15992e4:infod6:lengthi000e4:name4:temp12:piece lengthi12e9:root hash20:����&��JW�}�A4u,����ee diff --git a/test/test_torrents/invalid_root_hash.torrent b/test/test_torrents/invalid_root_hash.torrent deleted file mode 100644 index 442ecb6c581..00000000000 --- a/test/test_torrents/invalid_root_hash.torrent +++ /dev/null @@ -1 +0,0 @@ -d10:created by10:libtorrent13:creation datei1359599503e4:infod6:lengthi425e4:name4:temp12:piece lengthi16384e9:root hash19:���&��JW�}�A4u,����ee diff --git a/test/test_torrents/invalid_root_hash2.torrent b/test/test_torrents/invalid_root_hash2.torrent deleted file mode 100644 index 927fb07cdac..00000000000 --- a/test/test_torrents/invalid_root_hash2.torrent +++ /dev/null @@ -1 +0,0 @@ -d10:created by10:libtorrent13:creation datei1359599503e4:infod6:lengthi425e4:name4:temp12:piece lengthi16384e9:root hashi1343eee diff --git a/test/test_torrents/root_hash.torrent b/test/test_torrents/root_hash.torrent deleted file mode 100644 index 33666d7b0cd..00000000000 --- a/test/test_torrents/root_hash.torrent +++ /dev/null @@ -1 +0,0 @@ -d10:created by10:libtorrent13:creation datei1359599503e4:infod6:lengthi425e4:name4:temp12:piece lengthi16384e9:root hash20:����&��JW�}�A4u,����ee