Improve netaddress implementation #11231

pull danra wants to merge 4 commits into bitcoin:master from danra:refactor/safe-netaddress changing 2 files +226 −201
  1. danra commented at 5:40 PM on September 4, 2017: contributor

    Making most of the implementation simpler and safer.

  2. gmaxwell commented at 5:51 PM on September 4, 2017: contributor

    please don't add another boost dependency for a simple equality comparison.

  3. danra commented at 6:00 PM on September 4, 2017: contributor

    @gmaxwell There is already a dependency on this boost library in other places in the code. It doesn't have a standard equivalent, and it makes the code clearer here.

  4. gmaxwell commented at 6:27 PM on September 4, 2017: contributor

    @danra we are working on eliminating boost, and adding the additional header here visibly slows down the compile (30% longer for netaddress.cpp). If it were for something more complex than a match there might be an argument to use it for now and replace later, but it's just a string comparison and should be doable in one fairly clean and idiomatic line (slice and match; or reverse iterators).

  5. danra commented at 6:43 PM on September 4, 2017: contributor

    @gmaxwell If you don't mind, I'd be happy to discuss this a bit, since I think the approach of just "eliminating boost" is wrong.

    First of all, I don't that goal listed under the github "Projects" - I only see a goal of transitioning from boost to C++11. If removing boost in general from the project is a goal, even for cases where there is no standard substitute, I suppose it should be listed under "Projects" as well.

    Second, I think a reasonable compilation time increase is worth improving code clarity. Consider the "endswith" functionality here:

    • checking it inline instead of using a function requires a couple of if conditions, making it less readable and more error prone, which also means harder to review and less secure. One reading the code has only so much of an attention span, and it's bad to force details which are unnecessary in the context - implementing "endswith" inline is certainly out of the scope of the code where it is used.
    • Writing our own function is for the bitcoin repo in some utility header is fine, but it means a) using less tested code than the one boost uses and b) just more work which could be spent on more useful things.
  6. danra commented at 7:49 PM on September 4, 2017: contributor

    @gmaxwell Do you have a specific suggestion for an elegant one-liner? I don't see one which doesn't involve also checking the size, or doing some min() with it

  7. MarcoFalke added the label Refactoring on Sep 4, 2017
  8. MarcoFalke added the label P2P on Sep 4, 2017
  9. sipa commented at 10:36 PM on September 4, 2017: member

    I don't see anything wrong with

    template<typename T>
    bool BeginsWith(const T& a, const T& b)
    {
        return a.size() >= b.size() && std::equal(b.begin(), b.end(), a.begin());
    }
    
    template<typename T>
    bool EndWith(const T& a, const T& b)
    {
        return a.size() >= b.size() && std::equal(b.begin(), b.end(), a.end() - b.size());
    }
    
  10. meshcollider commented at 10:41 PM on September 4, 2017: contributor

    @danra It's written on there: The long term future goal is to remove Boost as a dependency.

  11. jimpo commented at 7:20 PM on September 5, 2017: contributor

    Should this be using .size() everywhere on the std::arrays instead of sizeof?

  12. danra commented at 7:28 PM on September 5, 2017: contributor

    @MeshCollider You're right. I think it's a bad goal, though (unlike boost->C++11 migration under which it's listed). For instance, is Bitcoin Core really interested in rewriting boost::multi_index?

  13. danra commented at 7:32 PM on September 5, 2017: contributor

    @jimpo I thought sizeof would be the same (and compile-time evaluable) since std::array is an aggregate type, but it seems that is not guaranteed. Will fix, thanks!

  14. danra commented at 8:44 PM on September 5, 2017: contributor

    @sipa It's not wrong, but this sort of utility functions tend to pile up, and I think it's better to use well-tested (e.g. boost provided) utility functions where it's available, rather than maintain them yourself, even if the cost is some compilation time. It makes the codebase easier to maintain and review -> more secure.

  15. sipa commented at 8:49 PM on September 5, 2017: member

    @danra That's a fair point, though I personally think that a boost dependency is worse than the cost of maintaining such a simple function.

  16. danra force-pushed on Sep 5, 2017
  17. danra commented at 8:58 PM on September 5, 2017: contributor

    @gmaxwell @sipa Reverted boost dependency, due to both your review and the fact that using the boost function changed the semantics slightly - the ".onion" address (with no preceding characters) was previously rejected immediately by the condition, which is probably safer than the situation after my modification which resulted in passing an empty string to DecodeBase32 (that function should handle empty strings correctly, but it's probably better to code defensively) @jimpo Fixed sizeof->size() (hopefully that would also fix onion address-related tests failing on some platforms :)

  18. in src/netaddress.cpp:311 in 46527f8b5d outdated
     308 |  }
     309 |  
     310 |  bool operator!=(const CNetAddr& a, const CNetAddr& b)
     311 |  {
     312 | -    return (memcmp(a.ip, b.ip, 16) != 0);
     313 | +    return !(a==b);
    


    promag commented at 7:46 AM on September 8, 2017:

    Nit, add spaces !(a == b).

  19. danra force-pushed on Sep 8, 2017
  20. Simplify CNetAddr method for setting raw IPv4/6 address
    Instead of having SetRaw() which asserts on the Network type to only be IPv4 or IPv6, which has two different implementations for the two cases anyway, just define two different methods SetRawIPv4 and SetRawIPv6. The only advantage of having a generic SetRaw accepting a Network type parameter would be for simplifying code in callers of the SetRaw method which are oblivious of the Network type, but there aren't even currently any calls to the SetRaw method from outside of the CNetAddr class.
    
    This is a preparation for the next commits will also need this change since we are going to use std::array instead of raw C-arrays, which means the parameter types of SetRawIPv4 and SetRawIPv6 will no longer be the same since they would be std::arrays of different length.
    
    In this commit we also change the parameter type of the SetRawIPv4/6 methods to be an unsigned char* instead of uint8_t*, since we pass in an aliased in_addr, and aliasing it to uint8_t* is non-standard. There's also no reason to use uint8_t anyway since we copy it into an unsigned char array.
    e74290e1d7
  21. Simplify and cleanup CNetAddr::SetSpecial() implementation 5798777a46
  22. Change CNetAddr code to modern C++ instead of C
    - Use std::array instead of C arrays.
    - Use algorithms where appropriate.
    - Use auto
    - Specify reinterpret_cast where it is done
    
    The above changes make the code safer and simplify most of the implementation.
    
    Also, some code was DRYed during the refactor, specifically sizeof is used where it makes sense instead of repeating hard-coded lengths of ips and ip prefixes.
    6d2af299df
  23. Misc style fixes according to Developer Notes e45306fa34
  24. danra force-pushed on Sep 8, 2017
  25. laanwj commented at 12:50 PM on April 26, 2018: member

    Closing due to inactivity, let me know if you start work on this again and want to re-open this.

  26. laanwj closed this on Apr 26, 2018

  27. MarcoFalke locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-22 06:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me