Add I2P support using I2P SAM #20685

pull vasild wants to merge 20 commits into bitcoin:master from vasild:i2p_sam changing 22 files +1304 −113
  1. vasild commented at 12:49 PM on December 17, 2020: member

    Add I2P support by using the I2P SAM protocol. Unlike Tor, for incoming connections we get the I2P address of the peer (and they also receive ours when we are the connection initiator).

    Two new options are added:

      -i2psam=<ip:port>
           I2P SAM proxy to reach I2P peers and accept I2P connections (default:
           none)
    
      -i2pacceptincoming
           If set and -i2psam is also set then incoming I2P connections are
           accepted via the SAM proxy. If this is not set but -i2psam is set
           then only outgoing connections will be made to the I2P network.
           Ignored if -i2psam is not set. Notice that listening for incoming
           I2P connections is done through the SAM proxy, not by binding to
           a local address and port (default: true)
    

    Overview of the changes

    Make ReadBinary() and WriteBinary() reusable

    We would need to dump the I2P private key to a file and read it back later. Move those two functions out of torcontrol.cpp.

    util: extract {Read,Write}BinaryFile() to its own files
    util: fix ReadBinaryFile() returning partial contents
    util: fix WriteBinaryFile() claiming success even if error occurred
    

    Split CConnman::AcceptConnection()

    Most of CConnman::AcceptConnection() is agnostic of how the socket was accepted. The other part of it deals with the details of the accept(2) system call. Split those so that the protocol-agnostic part can be reused if we accept a socket by other means.

    net: check for invalid socket earlier in CConnman::AcceptConnection()
    net: get the bind address earlier in CConnman::AcceptConnection()
    net: isolate the protocol-agnostic part of CConnman::AcceptConnection()
    net: avoid unnecessary GetBindAddress() call
    

    Implement the I2P SAM protocol (not all of it)

    Just the parts that would enable us to make outgoing and accept incoming I2P connections.

    net: extend CNetAddr::SetSpecial() to support I2P
    net: move the constant maxWait out of InterruptibleRecv()
    net: dedup MSG_NOSIGNAL and MSG_DONTWAIT definitions
    net: extend Sock::Wait() to report a timeout
    net: extend Sock with methods for robust send & read until terminator
    net: extend Sock with a method to check whether connected
    net: implement the necessary parts of the I2P SAM protocol
    

    Use I2P SAM to connect to and accept connections from I2P peers

    Profit from all of the preceding commits.

    init: introduce I2P connectivity options
    net: add I2P to the reachability map
    net: make outgoing I2P connections from CConnman
    net: accept incoming I2P connections from CConnman
    net: recognize I2P from ParseNetwork() so that -onlynet=i2p works
    net: Do not skip the I2P network from GetNetworkNames()
    
  2. DrahtBot added the label Build system on Dec 17, 2020
  3. DrahtBot added the label Docs on Dec 17, 2020
  4. DrahtBot added the label P2P on Dec 17, 2020
  5. DrahtBot added the label RPC/REST/ZMQ on Dec 17, 2020
  6. DrahtBot added the label Utils/log/libs on Dec 17, 2020
  7. laanwj commented at 3:36 PM on December 17, 2020: member

    Awesome work, concept ACK.

  8. DrahtBot commented at 8:13 PM on December 17, 2020: member

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #19461 (multiprocess: Add bitcoin-gui -ipcconnect option by ryanofsky)
    • #19460 (multiprocess: Add bitcoin-wallet -ipcconnect option by ryanofsky)
    • #19288 (fuzz: Add fuzzing harness for TorController by practicalswift)
    • #19160 (multiprocess: Add basic spawn and IPC support by ryanofsky)
    • #16365 (Log RPC parameters (arguments) if -debug=rpcparams by LarryRuane)
    • #10102 ([experimental] Multiprocess bitcoin by ryanofsky)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  9. naumenkogs commented at 9:05 AM on December 18, 2020: member

    Concept ACK


    Once this is enabled, we should clearly communicate that using a non-popular overlay has privacy/security side-effects

  10. practicalswift commented at 3:09 PM on December 18, 2020: contributor

    @vasild Nice work!

    I like the abstraction (Sock) you've added on top of the socket API. I'm adding something similar in #19203 (see MockableSocket and FuzzedSocket) to allow for fuzzing the more low-level parts of our networking code (in this specific case a regression fuzz harness for CVE-2017-18350).

    If you have time: please check that PR out. It would be great if your socket abstraction also covered the needs of the the "fuzzed socket" use case. Ideally I'd like to implement my low-level networking code fuzzers using your socket abstraction (something along the lines of class FuzzedSock : public Sock) :)

    Aside from of the I2P work I think your socket abstraction would be valuable on a stand-alone PR basis :)

  11. in src/util/readwritefile.cpp:29 in a0dc3a2d32 outdated
      24 | +        if (ferror(f)) {
      25 | +            fclose(f);
      26 | +            return std::make_pair(false,"");
      27 | +        }
      28 | +        retval.append(buffer, buffer+n);
      29 | +    } while (!feof(f) && retval.size() <= maxsize);
    


    lontivero commented at 6:58 PM on December 27, 2020:

    Q: in case retval contains the maximum allowed data shouldn't it get out of the loop? I mean, I know this is how the previous version of this method worked but I would like to understand why is this how it is.


    vasild commented at 8:27 AM on December 29, 2020:

    Yes, it should get out of the loop and it does due to retval.size() <= maxsize.

    It is true that if maxsize==10 and fread() returns 7 bytes and then 5 bytes, this function will return a retval that contains 12 bytes, exceeding maxsize. This is also how it works in master right now.

    For the purposes of this PR it suffices to move ReadBinaryFile() out of torcontrol.cpp so that it can be reused by other code. So I tried to keep changes to the minimum - moved the function and only fixed a gross bug (commit util: fix ReadBinaryFile() returning partial contents).

  12. in src/util/readwritefile.cpp:47 in a0dc3a2d32 outdated
      42 | +    }
      43 | +    if (fclose(f) != 0) {
      44 | +        return false;
      45 | +    }
      46 | +    return true;
      47 | +}
    


    lontivero commented at 7:26 PM on December 27, 2020:

    Non-cpp programmer question: is this idiomatically valid?

    bool WriteBinaryFile(const fs::path &filename, const std::string &data)
    {
        FILE *f = fsbridge::fopen(filename, "wb");
        if (f == nullptr)
            return false;
        if (fwrite(data.data(), 1, data.size(), f) == data.size()) {
            return fclose(f) == 0;
        }        
        fclose(f);
        return false;
    }
    

    vasild commented at 8:28 AM on December 29, 2020:

    Yes, those are the same. I guess, when writing new code, it would be a matter of taste which one to use.

  13. in src/util/strencodings.cpp:266 in a0dc3a2d32 outdated
     261 | @@ -262,21 +262,22 @@ std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid)
     262 |          }
     263 |          ++p;
     264 |      }
     265 | -    valid = valid && (p - e) % 8 == 0 && p - q < 8;
     266 | +    const bool pad_ok = (p - e) % 8 == 0 || !require_padding;
     267 | +    valid = valid && pad_ok && p - q < 8;
    


    lontivero commented at 8:43 PM on December 27, 2020:

    This makes my, my=, my== and so on until my===== all equivalent. Is this ok? I would have expected partial padding to be invalid.


    lontivero commented at 8:20 PM on December 28, 2020:

    Clarification: I am asking this because if this is allow then invalid addresses could be allowed by SetSpecial, I mean, something like udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna=.b32.i2p would be okay.


    vasild commented at 1:11 PM on December 29, 2020:

    Hah, good catch! It occurred to me that we need not to support decoding base32 strings without padding in general and instead we can append ==== to the 52 chars before .b32.i2p and decode it as padded base32 string.

    This simplifies this PR as I dropped one commit from it: util: support DecodeBase32() without padding. Also, added a check that the address is 52 base32 chars since we expect that adding 4 = symbols will make it multiple of 8. You suggested such a check elsewhere.

  14. lontivero commented at 8:44 PM on December 27, 2020: contributor

    Concept ACK (great work). Just a few questions.

  15. in src/netbase.cpp:1082 in a0dc3a2d32 outdated
    1074 | @@ -958,3 +1075,131 @@ void InterruptSocks5(bool interrupt)
    1075 |  {
    1076 |      interruptSocks5Recv = interrupt;
    1077 |  }
    1078 | +
    1079 | +
    1080 | +static inline bool IOErrorIsPermanent(int err)
    1081 | +{
    1082 | +    return err != WSAEAGAIN && err != WSAEWOULDBLOCK && err != WSAEINTR && err != WSAEINPROGRESS;
    


    jonatack commented at 5:48 PM on December 28, 2020:

    Build warning here, logical AND of equal expressions [-Wlogical-op]


    vasild commented at 9:51 AM on December 29, 2020:

    Is this on Windows? Which compiler version? Is it upset that WSAEAGAIN equals to WSAEWOULDBLOCK and so we end up doing something like err != 5 && err != 5?

    I checked that gcc 10.2.1, 9.3.0 and 8.4.0 don't emit the warning if we do err != 5 && err != 6 && err != 5, so I just reordered the expressions as a simple fixup ro this. Will include in the next push.


    jonatack commented at 10:22 AM on December 29, 2020:

    gcc Debian 10.2.1


    vasild commented at 1:00 PM on December 29, 2020:

    Fixed in f0577c4?


    jonatack commented at 4:23 PM on December 29, 2020:

    Yes, thank you -- tested that it is fixed in 188ba34 and in 2ae504c

  16. DrahtBot added the label Needs rebase on Dec 28, 2020
  17. vasild force-pushed on Dec 29, 2020
  18. vasild commented at 9:40 AM on December 29, 2020: member

    a0dc3a2d3...188ba34b4: rebased to resolve conflicts with master

  19. DrahtBot removed the label Needs rebase on Dec 29, 2020
  20. vasild force-pushed on Dec 29, 2020
  21. vasild commented at 12:59 PM on December 29, 2020: member

    188ba34b4...f0577c4d7:

    • disallow partial padding when decoding .b32.i2p addresses
    • fix gcc warning (hopefully)
  22. vasild force-pushed on Dec 29, 2020
  23. vasild commented at 1:27 PM on December 29, 2020: member

    f0577c4d7...2ae504c4b: allow uppercase and mixedcase I2P addresses, suggestion

  24. in src/netbase.cpp:1144 in 06286e5b83 outdated
    1140 | +    // at a time is about 50 times slower.
    1141 | +
    1142 | +    for (;;) {
    1143 | +        char buf[512];
    1144 | +
    1145 | +        const ssize_t peek_ret = recv(socket, buf, sizeof(buf), MSG_PEEK);
    


    lontivero commented at 10:14 PM on December 30, 2020:

    Time ago Winsock used to have problems with peeking from sockets. According to the KB article below (old) recv with MSG_PEEK:

    The peek operation will report the number of bytes up until the first buffer boundary. The bytes remaining in the other boundaries might never be reported, resulting in an incorrect count of data for code algorithms that depend upon the peek values to be accurate. Subsequent peek attempts will not reveal the "hidden" data, which can still be received from the buffers.

    I don't know if this is still a problem with winsock2 but even in that case it is probably not a problem this algorithm doesn't depend on the accuracy of the peek_ret value. Anyway, something to have in mind.

    https://mskb.pkisolutions.com/kb/192599


    vasild commented at 2:43 PM on December 31, 2020:

    Yeah, even if the behavior is still the same, we are fine with it.

  25. in src/netbase.cpp:1186 in 06286e5b83 outdated
    1181 | +            }
    1182 | +        }
    1183 | +
    1184 | +        const auto now = GetTime<std::chrono::milliseconds>();
    1185 | +
    1186 | +        if (now > deadline) {
    


    lontivero commented at 10:14 PM on December 30, 2020:

    I think that in case it reaches the deadline it should throw because otherwise the timeout will be infringed.

    if (now >= deadline)
    

    vasild commented at 2:46 PM on December 31, 2020:

    Right, and also SendComplete() uses >=. Changed.

  26. lontivero commented at 10:15 PM on December 30, 2020: contributor

    Partial review

  27. vasild force-pushed on Dec 31, 2020
  28. vasild commented at 2:47 PM on December 31, 2020: member

    2ae504c4b...9445dd490: consider it a timeout if the current time is exactly equal to the deadline

  29. DrahtBot added the label Needs rebase on Jan 2, 2021
  30. luke-jr commented at 12:22 AM on January 3, 2021: member

    Do we actually want to share our address, though? I would think an anonymous connection is strictly better?

  31. vasild commented at 1:39 PM on January 8, 2021: member

    Do we actually want to share our address, though?

    In I2P, like in IP, connections have "source address".

    I would think an anonymous connection is strictly better?

    Why? In a P2P network peers are supposed to connect to each other, right? Not hide from each other? If we don't want connections to us, then we don't listen on the I2P address (-i2pacceptincoming=0) and nobody can reach back.

  32. vasild force-pushed on Jan 9, 2021
  33. vasild commented at 12:25 PM on January 9, 2021: member

    9445dd490...1cced4679: rebase due to conflicts

  34. DrahtBot removed the label Needs rebase on Jan 9, 2021
  35. DrahtBot commented at 11:46 AM on January 13, 2021: member

    <!--4a62be1de6b64f3ed646cdc7932c8cf5-->

    🕵️ @harding @hebasto have been requested to review this pull request as specified in the REVIEWERS file.

  36. in src/i2p.cpp:194 in 1da3155d6e outdated
     189 | +                    RecvUntilTerminator(sock.Get(), '\n', MAX_WAIT_FOR_IO, *m_interrupt);
     190 | +
     191 | +                accepted.peer = CService(DestB64ToAddr(peer_dest), Params().GetDefaultPort());
     192 | +                accepted.socket = sock.Release();
     193 | +
     194 | +                err_wait = err_wait_begin;
    


    lontivero commented at 4:22 PM on January 13, 2021:

    I think this is unnecessary.


    vasild commented at 11:02 AM on January 15, 2021:

    You mean the incremental wait time or just this line?


    lontivero commented at 2:17 PM on January 15, 2021:

    Just this line because the next line is a return true;


    vasild commented at 12:13 PM on January 17, 2021:

    You are right, removed!

  37. in src/i2p.cpp:189 in 1da3155d6e outdated
     224 | +        }
     225 | +
     226 | +        const Reply& lookup_reply =
     227 | +            SendRequestAndGetReply(sock, strprintf("NAMING LOOKUP NAME=%s", to.ToStringIP()));
     228 | +
     229 | +        const std::string& dest = lookup_reply.Get("VALUE");
    


    lontivero commented at 4:30 PM on January 13, 2021:

    What if no VALUE is received?


    vasild commented at 11:06 AM on January 15, 2021:

    Then we will get an exception which is properly handled. Do you see any problems?


    lontivero commented at 2:13 PM on January 15, 2021:

    No, I don't see any problem, it is just that I didn't see the exception handling.


    vasild commented at 12:07 PM on January 17, 2021:

    Ok :)

  38. in src/i2p.cpp:247 in 1da3155d6e outdated
     282 | +
     283 | +    Reply reply;
     284 | +
     285 | +
     286 | +    // Don't log the full "SESSION CREATE ..." because it contains our private key.
     287 | +    reply.request = request.substr(0, 14) == "SESSION CREATE" ? "SESSION CREATE ..." : request;
    


    lontivero commented at 4:42 PM on January 13, 2021:

    If there is some kind of startsWith function i think it would be better.


    vasild commented at 12:07 PM on January 17, 2021:

    HasPrefix() is a good candidate, would need some enchanting.

  39. in src/i2p.cpp:266 in 1da3155d6e outdated
     301 | +        } else {
     302 | +            reply.keys.emplace(std::string{kv.begin(), kv.end()}, std::nullopt);
     303 | +        }
     304 | +    }
     305 | +
     306 | +    if (check_result_ok && reply.Get("RESULT") != "OK") {
    


    lontivero commented at 4:50 PM on January 13, 2021:

    It seems correct to assume that RESULT is always returned but in one place in the i2p code I can see this:

    } else if (ARG_IS(0,"NAMING") &&
               ARG_IS(1, "REPLY")) {
        if(NULL == (arg = ARG_FIND("RESULT"))) {
            SAMLOGS("Naming reply with no result");
           return 0;
       }
    

    lontivero commented at 4:51 PM on January 13, 2021:

    The Reply class could have a isOk() function, what do you think?


    vasild commented at 12:29 PM on January 15, 2021:

    Yes, if no RESULT is present then this function will throw an exception, which is ok. I think we should expect any reply from the I2P proxy, including malicious one.


    vasild commented at 12:31 PM on January 15, 2021:

    I think it is not worth to add isOk() method because it would be used in just one place - here and reply.Get("RESULT") != "OK" is readable enough.

  40. lontivero commented at 4:55 PM on January 13, 2021: contributor

    Partial review.

  41. felipsoarez commented at 4:15 PM on January 15, 2021: none

    utACK

  42. jonatack commented at 4:38 PM on January 15, 2021: member

    Concept ACK. This builds and runs cleanly. If anyone is running an i2p service, ping me on irc to try connecting to each other.

  43. in src/init.cpp:451 in 1cced46791 outdated
     446 | @@ -447,7 +447,9 @@ void SetupServerArgs(NodeContext& node)
     447 |      argsman.AddArg("-maxtimeadjustment", strprintf("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)", DEFAULT_MAX_TIME_ADJUSTMENT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
     448 |      argsman.AddArg("-maxuploadtarget=<n>", strprintf("Tries to keep outbound traffic under the given target (in MiB per 24h). Limit does not apply to peers with 'download' permission. 0 = no limit (default: %d)", DEFAULT_MAX_UPLOAD_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
     449 |      argsman.AddArg("-onion=<ip:port>", "Use separate SOCKS5 proxy to reach peers via Tor onion services, set -noonion to disable (default: -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
     450 | -    argsman.AddArg("-onlynet=<net>", "Make outgoing connections only through network <net> (ipv4, ipv6 or onion). Incoming connections are not affected by this option. This option can be specified multiple times to allow multiple networks.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
     451 | +    argsman.AddArg("-i2psam=<ip:port>", "I2P SAM proxy to reach I2P peers and accept I2P connections (default: none)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
     452 | +    argsman.AddArg("-i2pacceptincoming", "If set and -i2psam is also set then incoming I2P connections are accepted via the SAM proxy. If this is not set but -i2psam is set then only outgoing connections will be made to the I2P network. Ignored if -i2psam is not set. Notice that listening for incoming I2P connections is done through the SAM proxy, not by binding to a local address and port (default: true)", ArgsManager::ALLOW_BOOL, OptionsCategory::CONNECTION);
    


    laanwj commented at 11:23 PM on January 16, 2021:

    i'd use default: 1, not "true"


    vasild commented at 12:24 PM on January 17, 2021:

    Changed.

  44. jonatack commented at 11:53 AM on January 17, 2021: member

    We have an I2P-to-I2P Bitcoin network connection up this Sunday morning. EDIT: 2 connections :tada:

    Screenshot from 2021-01-17 13-40-57

    If helpful, I added the following setting to ~/.bitcoin/bitcoin.conf

    i2psam=127.0.0.1:7656
    
  45. mshalabi1990 commented at 12:01 PM on January 17, 2021: none

    It needs to be anonymous others wise i2p address will never work fully On Sun, Jan 17, 2021 at 6:55 AM Jon Atack notifications@github.com wrote:

    We have an I2P-to-I2P Bitcoin network connection up this Sunday morning.

    [image: Screenshot from 2021-01-17 11-41-47] https://user-images.githubusercontent.com/2415484/104839627-3027ad00-58ba-11eb-8cc6-8c572d222561.png

    If helpful, I added the following settings to ~/.bitcoin/bitcoin.conf

    i2psam=127.0.0.1:7656 i2pacceptincoming=1

    — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/bitcoin/bitcoin/pull/20685#issuecomment-761799484, or unsubscribe https://github.com/notifications/unsubscribe-auth/ASPKBM7LRCYPKYZKNVKG6GLS2LF4RANCNFSM4U7TL45Q .

  46. mshalabi1990 commented at 12:03 PM on January 17, 2021: none

    It needs to be annymous to full work or else it will never work fully decentralized

  47. vasild force-pushed on Jan 17, 2021
  48. vasild commented at 12:24 PM on January 17, 2021: member

    1cced4679...45e571315: rebase and address suggestions

  49. jonatack commented at 4:11 PM on January 17, 2021: member

    Stepping through the commits and building one-by-one.

    In 87ebd74 SocketEvents() interrupt is used like an "in" param but it is passed by reference like an "out" param

    +++ b/src/net.h
    @@ -1069,8 +1069,9 @@ private:
          * [@param](/bitcoin-bitcoin/contributor/param/)[in,out] sockets When the function is called this is expected to contain the
          * sockets that should be checked for readiness. Upon return only ready sockets are
          * left in it (non-ready sockets are removed).
    +     * [@param](/bitcoin-bitcoin/contributor/param/)[in] interrupt Cancel the operation if this is signaled.
          */
    -    void SocketEvents(Sockets& sockets);
    +    void SocketEvents(Sockets& sockets, CThreadInterrupt& interrupt);
    
  50. jonatack commented at 4:42 PM on January 17, 2021: member

    Starting from ad56288e9b2f, it seems the various std::chrono::milliseconds timeout params can be passed by value.

  51. in src/net.cpp:1046 in 45e571315a outdated
    1056 | -        NetPermissions::ClearFlag(permissionFlags, PF_ISIMPLICIT);
    1057 | -        if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) NetPermissions::AddFlag(permissionFlags, PF_FORCERELAY);
    1058 | -        if (gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) NetPermissions::AddFlag(permissionFlags, PF_RELAY);
    1059 | -        NetPermissions::AddFlag(permissionFlags, PF_MEMPOOL);
    1060 | -        NetPermissions::AddFlag(permissionFlags, PF_NOBAN);
    1061 | +    const CAddress& addr_bind = GetBindAddress(socket);
    


    jonatack commented at 5:37 PM on January 17, 2021:

    782de68a7008a

        const CAddress addr_bind = GetBindAddress(socket);
    

    vasild commented at 4:17 PM on January 18, 2021:

    Done.

  52. jonatack commented at 5:59 PM on January 17, 2021: member

    Consider dropping a3b33637f as the renaming is to a generic name that is less useful for searching for the variable in the code (false positives go from none to many), or renaming to a more unique name but the current one seems fine; this isn't new code.

    Edit: same feedback for ccc5966a; consider dropping the change or using a slightly less generic name, like permission_flags. This isn't new code, so you aren't required to rename the variables.

  53. jonatack commented at 6:01 PM on January 17, 2021: member

    Reviewed up to a3b33637f234c0f66bacd7afe0fd0dbe, one fixup in addition to the comments above.

  54. in src/netaddress.cpp:289 in 45e571315a outdated
     283 | @@ -275,6 +284,33 @@ bool CNetAddr::SetSpecial(const std::string& str)
     284 |      return false;
     285 |  }
     286 |  
     287 | +bool CNetAddr::SetI2P(const std::string& str)
     288 | +{
     289 | +    // I2P addresses that we support consist of 52 base32 characters + .b32.i2p.
    


    jonatack commented at 7:48 PM on January 17, 2021:

    484dc6559 suggest adding quotes and/or removing the trailing "." (if you add quotes here, maybe also line 298)

        // I2P addresses that we support consist of 52 base32 characters + ".b32.i2p"
    

    vasild commented at 4:16 PM on January 18, 2021:

    Added quotes, but left the dot.

    // Comments start with a capital letter and end with a dot, like real sentences.
    
    // Comments start with a capital letter and end with a dot, like real sentences. This
    // makes it easy to extend with another sentence.
    
  55. in src/test/net_tests.cpp:364 in 45e571315a outdated
     355 | +    const char* i2p_addr = "UDHDrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.I2P";
     356 | +    BOOST_REQUIRE(addr.SetSpecial(i2p_addr));
     357 | +    BOOST_REQUIRE(addr.IsValid());
     358 | +    BOOST_REQUIRE(addr.IsI2P());
     359 | +
     360 | +    BOOST_CHECK(!addr.IsBindAny());
    


    jonatack commented at 7:52 PM on January 17, 2021:

    484dc65591b perhaps a few additional sanity checks

    @@ -321,6 +321,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
         BOOST_REQUIRE(addr.IsTor());
     
    +    BOOST_CHECK(!addr.IsI2P());
         BOOST_CHECK(!addr.IsBindAny());
         BOOST_CHECK(addr.IsAddrV1Compatible());
         BOOST_CHECK_EQUAL(addr.ToString(), "6hzph5hv6337r6p2.onion");
    @@ -331,6 +332,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
         BOOST_REQUIRE(addr.IsTor());
     
    +    BOOST_CHECK(!addr.IsI2P());
         BOOST_CHECK(!addr.IsBindAny());
         BOOST_CHECK(!addr.IsAddrV1Compatible());
         BOOST_CHECK_EQUAL(addr.ToString(), torv3_addr);
    @@ -357,6 +359,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
         BOOST_REQUIRE(addr.IsI2P());
     
    +    BOOST_CHECK(!addr.IsTor());
         BOOST_CHECK(!addr.IsBindAny());
         BOOST_CHECK(!addr.IsAddrV1Compatible());
         BOOST_CHECK_EQUAL(addr.ToString(), ToLower(i2p_addr));
    

    vasild commented at 4:13 PM on January 18, 2021:

    Added, thanks!

  56. jonatack commented at 9:31 PM on January 17, 2021: member

    Reviewed up to 383bb95d49

  57. dunxen commented at 7:45 AM on January 18, 2021: contributor

    Concept ACK. Built and working with no major issues.

  58. vasild force-pushed on Jan 18, 2021
  59. vasild commented at 4:04 PM on January 18, 2021: member

    45e571315...b49a4a06e: address review suggestions

    SocketEvents() interrupt is used like an "in" param but it is passed by reference like an "out" param

    The sleep_for() method of CThreadInterrupt is not const, thus the variable is passed by non-const reference. I changed the comment to say @param[in,out].

    Starting from ad56288, it seems the various std::chrono::milliseconds timeout params can be passed by value.

    I am not sure those are trivial types like int, double, etc. Thus I pass them by const reference.

    Consider dropping a3b3363 as the renaming...

    Dropped the two renames, reducing the size of this PR.

    Note: if the above were posted as "review comments" attached to some line, then the replies would be next to them and also they could be hidden/collapsed once resolved.

  60. vasild commented at 4:40 PM on January 18, 2021: member

    A few notes:

    • We use SAM version 3.1 (HELLO VERSION MIN=3.1 MAX=3.1) because it is the maximum supported by the C++ i2p daemon (as of i2pd 2.35.0).

    • Ports seem to be ignored, so I default them to 8333. SAM 3.2 defines FROM_PORT and TO_PORT, but we use SAM 3.1. As a consequence we can connect to any port on a given I2P address - once we listen on foo.b32.i2p, a peer can connect to us on foo.b32.i2p:8333, foo.b32.i2p:1234, foo.b32.i2p:80, etc.

    • RemoveLocal() is not called if the connection to the I2P daemon dies, e.g. the I2P daemon is shut down. In order to stop advertising our I2P address (via other connections, if we have such ones, e.g. IPv4) we need to do that. Probably Session::Accept() needs to be split to two methods: Session:Listen() and Session::Accept(). Fixed.

  61. jonatack commented at 11:53 PM on January 18, 2021: member

    I am not sure those are trivial types like int, double, etc. Thus I pass them by const reference.

    IIUC according to https://en.cppreference.com/w/cpp/chrono/duration "The only data stored in a duration is a tick count of type Rep": std::chrono::milliseconds | duration</*signed integer type of at least 45 bits*/, std::milli>. If that is correct, it would be nice to avoid a situation like with CAmounts, which are a cheaply copied value but are passed around by reference to const all over this codebase, presumably because early on someone thought it wasn't cheap and then that style was replicated in code changes down the line. Not a huge issue but we may as well start off on the right foot.

  62. vasild force-pushed on Jan 22, 2021
  63. vasild commented at 8:41 AM on January 22, 2021: member

    b49a4a06e...39021d931:

    • Split the Accept() method to Listen() and Accept(), so that the caller from net.cpp can do AddLocal() when we are listening and RemoveLocal() when listening fails (e.g. the I2P proxy is shut down).

    • Do not AddLocal() after we connect to a I2P peer - should only do this when listening. As a result the newly added function AddLocalIfNotKnown() is not needed and thus dropped.

    • After a failure to listen, accept or connect - check whether the control socket is still connected and if not, then destroy the session. This is not strictly necessary, but makes us detect a possible I2P proxy shutdown earlier.

    • If -listen=0 is given, then soft-flip -i2pacceptincoming from 1 to 0. Still, if -listen=0 -i2pacceptincoming=1 is explicitly given, then allow that as there is no technical reason it would not work as expected (listen for and accept only I2P connections).

  64. vasild commented at 1:25 PM on January 22, 2021: member

    39021d931...7da1e29fc: rebase due to conflicts

  65. vasild force-pushed on Jan 22, 2021
  66. DrahtBot added the label Needs rebase on Jan 22, 2021
  67. DrahtBot removed the label Needs rebase on Jan 22, 2021
  68. DrahtBot added the label Needs rebase on Jan 26, 2021
  69. laanwj commented at 11:37 AM on January 26, 2021: member

    I'm still testing this on one of my nodes. It is working great. I've had a few connections to other I2P peers.

    I'm testing with the Java implementation of I2P, it has some typical java problems like high CPU and memory use. Compared to Tor at least. Of course, this is not the fault of this PR :slightly_smiling_face:

    Another thing (that @jonatack) noted is that I2P has higher latency than Tor onion services. At least I suppose this is an inherent problem with I2P and not the code here. Network latency is not generally a problem for bitcoin but as eviction decisions are made based on (among other things) ping times. This might be something to look into, but not necessarily in this PR, as a first step adding I2P support at all is a good and self-contained change.

  70. jonatack commented at 1:06 PM on January 26, 2021: member

    Another thing (that @jonatack) noted is that I2P has higher latency than Tor onion services. At least I suppose this is an inherent problem with I2P and not the code here. Network latency is not generally a problem for bitcoin but as eviction decisions are made based on (among other things) ping times. This might be something to look into, but not necessarily in this PR.

    Working on this either for #20197 or a follow-up.

  71. lontivero commented at 2:33 PM on January 28, 2021: contributor

    utACK 7da1e29fcc8a4fdff19f24d5be501ce4c0eeaa21

  72. vasild commented at 10:38 AM on January 29, 2021: member

    7da1e29fc...08d0c27d7: rebase due to conflicts

  73. vasild force-pushed on Jan 29, 2021
  74. vasild force-pushed on Jan 29, 2021
  75. vasild commented at 10:41 AM on January 29, 2021: member

    08d0c27d7...2caf1bff3: pass std::chrono variables by value instead of by const reference, as per suggestion. Thanks, @jonatack!

  76. DrahtBot removed the label Needs rebase on Jan 29, 2021
  77. laanwj removed the label Build system on Feb 3, 2021
  78. laanwj removed the label Docs on Feb 3, 2021
  79. laanwj removed the label RPC/REST/ZMQ on Feb 3, 2021
  80. laanwj removed the label Utils/log/libs on Feb 3, 2021
  81. laanwj added the label Feature on Feb 3, 2021
  82. jonatack commented at 5:15 PM on February 3, 2021: member

    I'd like to help move this forward. Is this pull independent of #20788?

  83. laanwj added this to the milestone 22.0 on Feb 3, 2021
  84. lontivero commented at 2:56 AM on February 4, 2021: contributor

    This PR is independent of #20788. However, #20788 was born as a subset of this PR because it adds goodness independently of this PR. Some of the suggestions made there and here (drop commits with renames, for example) have been made here but not in #20788 yet. Anyway, imo i think merging #20788 first could help to reduce the size of this one.

  85. jonatack commented at 3:13 PM on February 5, 2021: member

    @lontivero thank you, that is very helpful; will finishing reviewing here then as it is ahead of #20788 in its updates. @vasild you can drop my -netinfo commit now that #20764 is merged, sorry for the rebase (but it is now i2p-ready :sunglasses:)

  86. DrahtBot added the label Needs rebase on Feb 5, 2021
  87. fluffypony commented at 3:48 PM on February 5, 2021: contributor

    Per my conversation with @jonatack on Clubhouse, this i2p router that some Monero contributors have created may be of use: https://github.com/i2p-zero/i2p-zero

    It's VERY lightweight, even compared to i2pd and the full i2p router, implements SAM, and bundles a JVM.

  88. vasild force-pushed on Feb 6, 2021
  89. vasild commented at 1:52 PM on February 6, 2021: member

    2caf1bff3...2f71ee2b2: rebase due to conflicts and drop the last commit cli: add i2p network to -netinfo because an enhanced version of it is now in master via #20764. @jonatack, excellent, reducing the size of this PR! Getting #20788 merged will reduce it further.

  90. DrahtBot removed the label Needs rebase on Feb 6, 2021
  91. DrahtBot added the label Needs rebase on Feb 11, 2021
  92. jonatack commented at 1:26 PM on February 11, 2021: member

    Noting here some IRC discussions on installing I2P as a reference for later, e.g. a future doc/i2p.md, or for people looking to install it:

  93. vasild force-pushed on Feb 13, 2021
  94. DrahtBot removed the label Needs rebase on Feb 13, 2021
  95. vasild commented at 1:17 PM on February 13, 2021: member

    2f71ee2b2...a456bd3f2:

    • Remove the Sock definition from this PR as it is now merged in master.
    • Do not extract CConnman::SocketEvents() as a standalone function since it is not needed anymore - in all places we wait for an event on one socket and for this we can use Sock::Wait().
    • Extend Sock::Wait() to report to the caller whether a timeout occurred or one of the requested events.
    • Add SendComplete() and RecvUntilTerminator() as Sock methods instead of as standalone functions whose first argument is the socket.
    • When generating our pub/priv keys (aka I2P destination) use 7 instead of EdDSA_SHA512_Ed25519 since i2pd <2.24.0 only understand the numeric one (thanks to @sdaftuar for nailing this!)
  96. laanwj commented at 10:37 PM on February 13, 2021: member

    Updated my I2P-using node to the new version (a456bd3f296f18e463e36048c866c404b69363b6) for testing.

  97. jonatack commented at 12:20 AM on February 14, 2021: member

    Testing a Clang 9 build of a456bd3f296f18e463e36048c866c404b69363b6 with i2pd 2.35 did not work

    2021-02-13T23:31:35Z I2P: SAM session created: session id=86eaxxaxxxx, my address=zsxwyo6qcn3chqzwxnseusqgsnuw3maqnztkiypyfxtyxxxxxxxx.b32.i2p:8333
    2021-02-13T23:31:35Z AddLocal(zsxwyo6qcn3chqzwxnseusqgsnuw3maqnztkiypyfxtyxxxxxxxx.b32.i2p:8333,2)
    Illegal instruction
    
    Debian 5.10.13-1 (2021-02-06) x86_64 GNU/Linux
    
    i2pd version 2.35.0 (0.9.48)
    Boost version 1.74.0
    OpenSSL 1.1.1i  8 Dec 2020
    

    Made two further attempts with the same result :crying_cat_face:...it's after 1 am and I have not yet looked into the code changes since the last push, but then built with the same config on 2f71ee2b2 (previous push) and it's working again...:cat:

  98. laanwj commented at 10:53 AM on February 14, 2021: member

    2021-02-13T23:31:35Z AddLocal(zsxwyo6qcn3chqzwxnseusqgsnuw3maqnztkiypyfxtyxxxxxxxx.b32.i2p:8333,2) Illegal instruction

    Can you give a gdb backtrace please? With disassembly (disass) at the crash location, if possible. The post common cause of Illegal Instruction is your compiler generating extension instructions that the specific CPU can't handle. I don't understand how it could be introduced here though.

  99. jonatack commented at 2:54 PM on February 14, 2021: member

    Hm, gdb didn't hit the issue (I'll try again) but valgrind did.

    2021-02-14T14:45:19Z New outbound peer connected: version: 70015, blocks=670586, peer=1, peeraddr=144.76.81.194:8333 (outbound-full-relay)
    2021-02-14T14:45:39Z I2P: SAM session created: session id=qqqq, my address=qqqq.b32.i2p:8333
    2021-02-14T14:45:41Z UpdateTip: new best=00000000000000000009e0b532bf3ff388c9d7c4489b0bcf2631f75195609c57 height=670580 version=0x3fff0000 log2_work=92.668088 tx=616177992 date='2021-02-14T13:15:07Z' progress=0.999969 cache=1.5MiB(10863txo)
    2021-02-14T14:45:41Z AddLocal(qqqq.b32.i2p:8333,2)
    ==5137== valgrind: Unrecognised instruction at address 0x17e85a.
    ==5137==    at 0x17E85A: CConnman::ConnectNode(CAddress, char const*, bool, ConnectionType) (net.cpp:437)
    ==5137==    by 0x188529: CConnman::OpenNetworkConnection(CAddress const&, bool, CSemaphoreGrant*, char const*, ConnectionType) (net.cpp:2152)
    ==5137==    by 0x192136: CConnman::ThreadOpenAddedConnections() (net.cpp:2119)
    ==5137==    by 0x1AABAD: __invoke_impl<void, void (CConnman::*&)(), CConnman *&> (invoke.h:73)
    ==5137==    by 0x1AABAD: __invoke<void (CConnman::*&)(), CConnman *&> (invoke.h:95)
    ==5137==    by 0x1AABAD: __call<void, 0> (functional:416)
    ==5137==    by 0x1AABAD: operator()<, void> (functional:499)
    ==5137==    by 0x1AABAD: __invoke_impl<void, std::_Bind<void (CConnman::*(CConnman *))()> &> (invoke.h:60)
    ==5137==    by 0x1AABAD: __invoke_r<void, std::_Bind<void (CConnman::*(CConnman *))()> &> (invoke.h:110)
    ==5137==    by 0x1AABAD: std::_Function_handler<void (), std::_Bind<void (CConnman::*(CConnman*))()> >::_M_invoke(std::_Any_data const&) (std_function.h:291)
    ==5137==    by 0x16A038: operator() (std_function.h:622)
    ==5137==    by 0x16A038: void TraceThread<std::function<void ()> >(char const*, std::function<void ()>) (system.h:470)
    ==5137==    by 0x1AAD7F: __invoke_impl<void, void (*)(const char *, std::function<void ()>), const char *, std::function<void ()> > (invoke.h:60)
    ==5137==    by 0x1AAD7F: __invoke<void (*)(const char *, std::function<void ()>), const char *, std::function<void ()> > (invoke.h:95)
    ==5137==    by 0x1AAD7F: _M_invoke<0, 1, 2> (thread:264)
    ==5137==    by 0x1AAD7F: operator() (thread:271)
    ==5137==    by 0x1AAD7F: std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, std::function<void ()> > > >::_M_run() (thread:215)
    ==5137==    by 0x4DE1ECF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
    ==5137==    by 0x4875EA6: start_thread (pthread_create.c:477)
    ==5137==    by 0x513DDEE: clone (clone.S:95)
    ==5137== Your program just tried to execute an instruction that Valgrind
    ==5137== did not recognise.  There are two possible reasons for this.
    ==5137== 1. Your program has a bug and erroneously jumped to a non-code
    ==5137==    location.  If you are running Memcheck and you just saw a
    ==5137==    warning about a bad jump, it's probably your program's fault.
    ==5137== 2. The instruction is legitimate but Valgrind doesn't handle it,
    ==5137==    i.e. it's Valgrind's fault.  If you think this is the case or
    ==5137==    you are not sure, please let us know and we'll try to fix it.
    ==5137== Either way, Valgrind will now raise a SIGILL signal which will
    ==5137== probably kill your program.
    ==5137== 
    ==5137== Process terminating with default action of signal 4 (SIGILL)
    ==5137==  Illegal opcode at address 0x17E85A
    ==5137==    at 0x17E85A: CConnman::ConnectNode(CAddress, char const*, bool, ConnectionType) (net.cpp:437)
    ==5137==    by 0x188529: CConnman::OpenNetworkConnection(CAddress const&, bool, CSemaphoreGrant*, char const*, ConnectionType) (net.cpp:2152)
    ==5137==    by 0x192136: CConnman::ThreadOpenAddedConnections() (net.cpp:2119)
    ==5137==    by 0x1AABAD: __invoke_impl<void, void (CConnman::*&)(), CConnman *&> (invoke.h:73)
    ==5137==    by 0x1AABAD: __invoke<void (CConnman::*&)(), CConnman *&> (invoke.h:95)
    ==5137==    by 0x1AABAD: __call<void, 0> (functional:416)
    ==5137==    by 0x1AABAD: operator()<, void> (functional:499)
    ==5137==    by 0x1AABAD: __invoke_impl<void, std::_Bind<void (CConnman::*(CConnman *))()> &> (invoke.h:60)
    ==5137==    by 0x1AABAD: __invoke_r<void, std::_Bind<void (CConnman::*(CConnman *))()> &> (invoke.h:110)
    ==5137==    by 0x1AABAD: std::_Function_handler<void (), std::_Bind<void (CConnman::*(CConnman*))()> >::_M_invoke(std::_Any_data const&) (std_function.h:291)
    ==5137==    by 0x16A038: operator() (std_function.h:622)
    ==5137==    by 0x16A038: void TraceThread<std::function<void ()> >(char const*, std::function<void ()>) (system.h:470)
    ==5137==    by 0x1AAD7F: __invoke_impl<void, void (*)(const char *, std::function<void ()>), const char *, std::function<void ()> > (invoke.h:60)
    ==5137==    by 0x1AAD7F: __invoke<void (*)(const char *, std::function<void ()>), const char *, std::function<void ()> > (invoke.h:95)
    ==5137==    by 0x1AAD7F: _M_invoke<0, 1, 2> (thread:264)
    ==5137==    by 0x1AAD7F: operator() (thread:271)
    ==5137==    by 0x1AAD7F: std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, std::function<void ()> > > >::_M_run() (thread:215)
    ==5137==    by 0x4DE1ECF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
    ==5137==    by 0x4875EA6: start_thread (pthread_create.c:477)
    ==5137==    by 0x513DDEE: clone (clone.S:95)
    ==5137== 
    ==5137== HEAP SUMMARY:
    ==5137==     in use at exit: 238,728,213 bytes in 1,629,048 blocks
    ==5137==   total heap usage: 9,884,111 allocs, 8,255,063 frees, 4,818,980,752 bytes allocated
    ==5137== 
    ==5137== LEAK SUMMARY:
    ==5137==    definitely lost: 562,000 bytes in 138 blocks
    ==5137==    indirectly lost: 0 bytes in 0 blocks
    ==5137==      possibly lost: 7,987,784 bytes in 414 blocks
    ==5137==    still reachable: 230,178,429 bytes in 1,628,496 blocks
    ==5137==                       of which reachable via heuristic:
    ==5137==                         length64           : 213,760 bytes in 360 blocks
    ==5137==                         newarray           : 72 bytes in 1 blocks
    ==5137==         suppressed: 0 bytes in 0 blocks
    ==5137== Rerun with --leak-check=full to see details of leaked memory
    ==5137== 
    ==5137== Use --track-origins=yes to see where uninitialised values come from
    ==5137== For lists of detected and suppressed errors, rerun with: -s
    ==5137== ERROR SUMMARY: 9 errors from 1 contexts (suppressed: 0 from 0)
    Illegal instruction
    
  100. jonatack commented at 3:57 PM on February 14, 2021: member

    Ok, hit it with gdb

    2021-02-14T15:33:36Z I2P: SAM session created: session id=qqqq, my address=h3r6bkn4...q.b32.i2p:8333
    2021-02-14T15:33:36Z AddLocal(h3r6bkn4...q.b32.i2p:8333,2)
    
    Thread 18 "b-addcon" received signal SIGSEGV, Segmentation fault.
    [Switching to Thread 0x7fff39ed7700 (LWP 54120)]
    0x0000555555621ede in CConnman::ConnectNode (this=0x5555566e3ec0, addrConnect=..., 
        pszDest=0x7fff28002e50 "h3r6bkn4...q.b32.i2p", fCountFailure=false, conn_type=ConnectionType::MANUAL) at net.cpp:437
    437	                *sock = std::move(conn.sock);
    

    <details><summary>backtrace</summary><p>

    (gdb) bt
    [#0](/bitcoin-bitcoin/0/)  0x0000555555621ede in CConnman::ConnectNode (this=0x5555566e3ec0, addrConnect=..., 
        pszDest=0x7fff28002e50 "qqqq.b32.i2p", fCountFailure=false, conn_type=ConnectionType::MANUAL) at net.cpp:437
    [#1](/bitcoin-bitcoin/1/)  0x0000555555629c1e in CConnman::OpenNetworkConnection (this=0x5555566e3ec0, addrConnect=..., fCountFailure=false, grantOutbound=0x7fff39ed6830, 
        pszDest=0x7fff28002e50 "qqqq.b32.i2p", conn_type=ConnectionType::MANUAL) at net.cpp:2152
    [#2](/bitcoin-bitcoin/2/)  0x000055555563195a in CConnman::ThreadOpenAddedConnections (this=0x5555566e3ec0) at net.cpp:2119
    [#3](/bitcoin-bitcoin/3/)  0x00005555556902c8 in std::__invoke_impl<void, void (CConnman::*&)(), CConnman*&> (
        __f=@0x5555603a3f60: (void (CConnman::*)(CConnman * const)) 0x5555556317c0 <CConnman::ThreadOpenAddedConnections()>, __t=@0x5555603a3f70: 0x5555566e3ec0)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:73
    [#4](/bitcoin-bitcoin/4/)  0x0000555555690163 in std::__invoke<void (CConnman::*&)(), CConnman*&> (
        __fn=@0x5555603a3f60: (void (CConnman::*)(CConnman * const)) 0x5555556317c0 <CConnman::ThreadOpenAddedConnections()>, __args=@0x5555603a3f70: 0x5555566e3ec0)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:95
    [#5](/bitcoin-bitcoin/5/)  0x00005555556900f4 in std::_Bind<void (CConnman::*(CConnman*))()>::__call<void, , 0ul>(std::tuple<>&&, std::_Index_tuple<0ul>) (this=0x5555603a3f60, __args=...)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/functional:416
    [#6](/bitcoin-bitcoin/6/)  0x0000555555690077 in std::_Bind<void (CConnman::*(CConnman*))()>::operator()<, void>() (this=0x5555603a3f60)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/functional:499
    [#7](/bitcoin-bitcoin/7/)  0x000055555568ffce in std::__invoke_impl<void, std::_Bind<void (CConnman::*(CConnman*))()>&>(std::__invoke_other, std::_Bind<void (CConnman::*(CConnman*))()>&) (
        __f=...) at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:60
    [#8](/bitcoin-bitcoin/8/)  0x000055555568ff1e in std::__invoke_r<void, std::_Bind<void (CConnman::*(CConnman*))()>&>(std::_Bind<void (CConnman::*(CConnman*))()>&) (__fn=...)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:110
    [#9](/bitcoin-bitcoin/9/)  0x000055555568fbae in std::_Function_handler<void (), std::_Bind<void (CConnman::*(CConnman*))()> >::_M_invoke(std::_Any_data const&) (__functor=...)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h:291
    [#10](/bitcoin-bitcoin/10/) 0x0000555555614dff in std::function<void ()>::operator()() const (this=0x7fff39ed6b48)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h:622
    [#11](/bitcoin-bitcoin/11/) 0x00005555555d4f40 in TraceThread<std::function<void ()> >(char const*, std::function<void ()>) (name=0x55555611dc37 "addcon", func=...) at ./util/system.h:470
    [#12](/bitcoin-bitcoin/12/) 0x0000555555691182 in std::__invoke_impl<void, void (*)(char const*, std::function<void ()>), char const*, std::function<void ()> >(std::__invoke_other, void (*&&)(char const*, std::function<void ()>), char const*&&, std::function<void ()>&&) (
        __f=@0x5555603a41f0: 0x5555555d4eb0 <TraceThread<std::function<void ()> >(char const*, std::function<void ()>)>, __args=..., __args=...)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:60
    [#13](/bitcoin-bitcoin/13/) 0x0000555555690f78 in std::__invoke<void (*)(char const*, std::function<void ()>), char const*, std::function<void ()> >(void (*&&)(char const*, std::function<void ()>), char const*&&, std::function<void ()>&&) (__fn=@0x5555603a41f0: 0x5555555d4eb0 <TraceThread<std::function<void ()> >(char const*, std::function<void ()>)>, 
        __args=..., __args=...) at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:95
    [#14](/bitcoin-bitcoin/14/) 0x0000555555690eff in std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, std::function<void ()> > >::_M_invoke<0ul, 1ul, 2ul>(std::_Index_tuple<0ul, 1ul, 2ul>) (this=0x5555603a41c8) at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/thread:264
    [#15](/bitcoin-bitcoin/15/) 0x0000555555690e66 in std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, std::function<void ()> > >::operator()() (
        this=0x5555603a41c8) at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/thread:271
    [#16](/bitcoin-bitcoin/16/) 0x00005555556909ed in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, std::function<void ()> > > >::_M_run() (this=0x5555603a41c0) at /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/thread:215
    [#17](/bitcoin-bitcoin/17/) 0x00007ffff79ffed0 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
    [#18](/bitcoin-bitcoin/18/) 0x00007ffff7f8aea7 in start_thread (arg=<optimized out>) at pthread_create.c:477
    [#19](/bitcoin-bitcoin/19/) 0x00007ffff7709def in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
    

    </p></details>

    <details><summary>disassembly</summary><p>

    (gdb) disass /m
    Dump of assembler code for function _ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType:
    377	{
       0x0000555555621490 <+0>:	endbr64 
       0x0000555555621494 <+4>:	push   %rbp
       0x0000555555621495 <+5>:	mov    %rsp,%rbp
       0x0000555555621498 <+8>:	sub    $0x620,%rsp
       0x000055555562149f <+15>:	mov    %fs:0x28,%rax
       0x00005555556214a8 <+24>:	mov    %rax,-0x8(%rbp)
       0x00005555556214ac <+28>:	mov    %rdi,-0x3c8(%rbp)
       0x00005555556214b3 <+35>:	mov    %rdx,-0x340(%rbp)
       0x00005555556214ba <+42>:	and    $0x1,%cl
       0x00005555556214bd <+45>:	mov    %cl,-0x3c9(%rbp)
       0x00005555556214c3 <+51>:	mov    %r8d,-0x3d0(%rbp)
       0x00005555556214ca <+58>:	mov    -0x3c8(%rbp),%rax
    
    378	    assert(conn_type != ConnectionType::INBOUND);
       0x00005555556214d1 <+65>:	cmpl   $0x0,-0x3d0(%rbp)
       0x00005555556214d8 <+72>:	mov    %rsi,-0x428(%rbp)
       0x00005555556214df <+79>:	mov    %rax,-0x430(%rbp)
       0x00005555556214e6 <+86>:	je     0x5555556214f1 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+97>
       0x00005555556214ec <+92>:	jmp    0x555555621510 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+128>
       0x00005555556214f1 <+97>:	lea    0xafb9c5(%rip),%rdi        # 0x55555611cebd
       0x00005555556214f8 <+104>:	lea    0xb26cd2(%rip),%rsi        # 0x5555561481d1
       0x00005555556214ff <+111>:	mov    $0x17a,%edx
       0x0000555555621504 <+116>:	lea    0xafb9d7(%rip),%rcx        # 0x55555611cee2
       0x000055555562150b <+123>:	call   0x555555581490 <__assert_fail@plt>
    
    379	
    380	    if (pszDest == nullptr) {
       0x0000555555621510 <+128>:	cmpq   $0x0,-0x340(%rbp)
       0x0000555555621518 <+136>:	jne    0x5555556215e4 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+340>
       0x000055555562151e <+142>:	mov    -0x428(%rbp),%rax
    
    381	        if (IsLocal(addrConnect))
       0x0000555555621525 <+149>:	mov    %rax,%rdi
       0x0000555555621528 <+152>:	call   0x555555620940 <_Z7IsLocalRK8CService>
       0x000055555562152d <+157>:	test   $0x1,%al
       0x000055555562152f <+159>:	jne    0x55555562153a <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+170>
       0x0000555555621535 <+165>:	jmp    0x55555562154a <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+186>
    
    382	            return nullptr;
       0x000055555562153a <+170>:	movq   $0x0,-0x3c0(%rbp)
       0x0000555555621545 <+181>:	jmp    0x5555556228fd <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5229>
       0x000055555562154a <+186>:	lea    -0x30(%rbp),%rax
    
    383	
    384	        // Look for an existing connection
    385	        CNode* pnode = FindNode(static_cast<CService>(addrConnect));
       0x000055555562154e <+190>:	mov    %rax,%rdi
       0x0000555555621551 <+193>:	mov    -0x428(%rbp),%rsi
       0x0000555555621558 <+200>:	mov    %rax,-0x438(%rbp)
       0x000055555562155f <+207>:	call   0x5555555d5980 <_ZN8CServiceC2ERKS_>
       0x0000555555621564 <+212>:	mov    -0x430(%rbp),%rdi
       0x000055555562156b <+219>:	mov    -0x438(%rbp),%rsi
       0x0000555555621572 <+226>:	call   0x555555620fe0 <_ZN8CConnman8FindNodeERK8CService>
       0x0000555555621577 <+231>:	mov    %rax,-0x440(%rbp)
       0x000055555562157e <+238>:	jmp    0x555555621583 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+243>
       0x0000555555621583 <+243>:	lea    -0x30(%rbp),%rdi
       0x0000555555621587 <+247>:	call   0x5555555d3b20 <_ZN8CServiceD2Ev>
       0x000055555562158c <+252>:	mov    -0x440(%rbp),%rax
       0x0000555555621593 <+259>:	mov    %rax,-0x3d8(%rbp)
       0x00005555556215d1 <+321>:	lea    -0x30(%rbp),%rdi
       0x00005555556215d5 <+325>:	call   0x5555555d3b20 <_ZN8CServiceD2Ev>
       0x00005555556215da <+330>:	jmp    0x555555622931 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5281>
       0x0000555555622931 <+5281>:	mov    -0x3e0(%rbp),%rdi
       0x0000555555622938 <+5288>:	call   0x5555555821a0 <_Unwind_Resume@plt>
       0x000055555562293d <+5293>:	call   0x5555555817d0 <__stack_chk_fail@plt>
       0x0000555555622942:	nopw   %cs:0x0(%rax,%rax,1)
       0x000055555562294c:	nopl   0x0(%rax)
    
    386	        if (pnode)
       0x000055555562159a <+266>:	cmpq   $0x0,-0x3d8(%rbp)
       0x00005555556215a2 <+274>:	je     0x5555556215df <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+335>
    
    387	        {
    388	            LogPrintf("Failed to open new connection, already connected\n");
       0x00005555556215a8 <+280>:	lea    0xafb97e(%rip),%rdi        # 0x55555611cf2d
       0x00005555556215af <+287>:	call   0x555555622950 <_ZL9LogPrintfIJEEvPKcDpRKT_>
    
    389	            return nullptr;
       0x00005555556215b4 <+292>:	movq   $0x0,-0x3c0(%rbp)
       0x00005555556215bf <+303>:	jmp    0x5555556228fd <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5229>
    
    390	        }
    391	    }
       0x00005555556215df <+335>:	jmp    0x5555556215e4 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+340>
    
    392	
    393	    /// debug print
    394	    LogPrint(BCLog::NET, "trying connection %s lastseen=%.1fhrs\n",
       0x00005555556215e4 <+340>:	jmp    0x5555556215e9 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+345>
       0x00005555556215e9 <+345>:	mov    $0x1,%edi
       0x00005555556215ee <+350>:	call   0x55555561fd20 <_ZL17LogAcceptCategoryN5BCLog8LogFlagsE>
       0x00005555556215f3 <+355>:	test   $0x1,%al
       0x00005555556215f5 <+357>:	jne    0x555555621600 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+368>
       0x00005555556215fb <+363>:	jmp    0x5555556217a1 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+785>
       0x0000555555621600 <+368>:	mov    -0x340(%rbp),%rax
       0x0000555555621607 <+375>:	movb   $0x0,-0x3e5(%rbp)
       0x000055555562160e <+382>:	cmp    $0x0,%rax
       0x0000555555621612 <+386>:	je     0x555555621664 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+468>
       0x0000555555621618 <+392>:	mov    -0x340(%rbp),%rsi
       0x000055555562161f <+399>:	lea    -0x348(%rbp),%rax
       0x0000555555621626 <+406>:	mov    %rax,%rdi
       0x0000555555621629 <+409>:	mov    %rsi,-0x448(%rbp)
       0x0000555555621630 <+416>:	mov    %rax,-0x450(%rbp)
       0x0000555555621637 <+423>:	call   0x555555582c40 <_ZNSaIcEC1Ev@plt>
       0x000055555562163c <+428>:	movb   $0x1,-0x3e5(%rbp)
       0x0000555555621643 <+435>:	lea    -0x50(%rbp),%rdi
       0x0000555555621647 <+439>:	mov    -0x448(%rbp),%rsi
       0x000055555562164e <+446>:	mov    -0x450(%rbp),%rdx
       0x0000555555621655 <+453>:	call   0x55555559c0c0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC2IS3_EEPKcRKS3_>
       0x000055555562165a <+458>:	jmp    0x55555562165f <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+463>
       0x000055555562165f <+463>:	jmp    0x55555562167e <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+494>
       0x0000555555621664 <+468>:	lea    -0x50(%rbp),%rdi
       0x0000555555621668 <+472>:	mov    -0x428(%rbp),%rsi
       0x000055555562166f <+479>:	call   0x555555eaef60 <_ZNK8CService8ToStringB5cxx11Ev>
       0x0000555555621674 <+484>:	jmp    0x555555621679 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+489>
       0x0000555555621679 <+489>:	jmp    0x55555562167e <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+494>
       0x000055555562167e <+494>:	cmpq   $0x0,-0x340(%rbp)
       0x0000555555621686 <+502>:	je     0x55555562169c <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+524>
       0x000055555562168c <+508>:	xorps  %xmm0,%xmm0
       0x000055555562168f <+511>:	movsd  %xmm0,-0x458(%rbp)
       0x0000555555621697 <+519>:	jmp    0x5555556216fe <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+622>
       0x000055555562169c <+524>:	call   0x5555559d35f0 <_Z15GetAdjustedTimev>
       0x00005555556216a1 <+529>:	mov    %rax,-0x460(%rbp)
       0x00005555556216a8 <+536>:	jmp    0x5555556216ad <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+541>
       0x00005555556216ad <+541>:	mov    -0x428(%rbp),%rax
       0x00005555556216b4 <+548>:	mov    0x24(%rax),%ecx
       0x00005555556216b7 <+551>:	mov    %ecx,%edx
       0x00005555556216b9 <+553>:	mov    -0x460(%rbp),%rsi
       0x00005555556216c0 <+560>:	sub    %rdx,%rsi
       0x00005555556216c3 <+563>:	seto   %dil
       0x00005555556216c7 <+567>:	xor    $0xff,%dil
       0x00005555556216cb <+571>:	test   $0x1,%dil
       0x00005555556216cf <+575>:	mov    %rsi,-0x468(%rbp)
       0x00005555556216d6 <+582>:	jne    0x5555556216de <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+590>
       0x00005555556216dc <+588>:	ud2    
       0x00005555556216de <+590>:	movsd  0xafb552(%rip),%xmm0        # 0x55555611cc38
       0x00005555556216e6 <+598>:	mov    -0x468(%rbp),%rax
       0x00005555556216ed <+605>:	cvtsi2sd %rax,%xmm1
       0x00005555556216f2 <+610>:	divsd  %xmm0,%xmm1
       0x00005555556216f6 <+614>:	movsd  %xmm1,-0x458(%rbp)
       0x00005555556216fe <+622>:	movsd  -0x458(%rbp),%xmm0
       0x0000555555621706 <+630>:	movsd  %xmm0,-0x350(%rbp)
       0x000055555562170e <+638>:	lea    0xafb84a(%rip),%rdi        # 0x55555611cf5f
       0x0000555555621715 <+645>:	lea    -0x50(%rbp),%rsi
       0x0000555555621719 <+649>:	lea    -0x350(%rbp),%rdx
       0x0000555555621720 <+656>:	call   0x555555622c30 <_ZL9LogPrintfIJNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEdEEvPKcDpRKT_>
       0x0000555555621725 <+661>:	jmp    0x55555562172a <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+666>
       0x000055555562172a <+666>:	lea    -0x50(%rbp),%rdi
       0x000055555562172e <+670>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x0000555555621733 <+675>:	testb  $0x1,-0x3e5(%rbp)
       0x000055555562173a <+682>:	jne    0x555555621745 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+693>
       0x0000555555621740 <+688>:	jmp    0x555555621751 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+705>
       0x0000555555621745 <+693>:	lea    -0x348(%rbp),%rdi
       0x000055555562174c <+700>:	call   0x5555555833a0 <_ZNSaIcED1Ev@plt>
       0x0000555555621751 <+705>:	jmp    0x5555556217a1 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+785>
       0x0000555555621775 <+741>:	lea    -0x50(%rbp),%rdi
       0x0000555555621779 <+745>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x000055555562177e <+750>:	testb  $0x1,-0x3e5(%rbp)
       0x0000555555621785 <+757>:	jne    0x555555621790 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+768>
       0x000055555562178b <+763>:	jmp    0x55555562179c <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+780>
       0x0000555555621790 <+768>:	lea    -0x348(%rbp),%rdi
       0x0000555555621797 <+775>:	call   0x5555555833a0 <_ZNSaIcED1Ev@plt>
       0x000055555562179c <+780>:	jmp    0x555555622931 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5281>
       0x00005555556217a1 <+785>:	jmp    0x5555556217a6 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+790>
    
    395	        pszDest ? pszDest : addrConnect.ToString(),
    396	        pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
    397	
    398	    // Resolve
    399	    const int default_port = Params().GetDefaultPort();
       0x00005555556217a6 <+790>:	call   0x555555e7b5b0 <_Z6Paramsv>
       0x00005555556217ab <+795>:	mov    %rax,%rdi
       0x00005555556217ae <+798>:	call   0x5555555cf590 <_ZNK12CChainParams14GetDefaultPortEv>
       0x00005555556217b3 <+803>:	mov    %eax,-0x3ec(%rbp)
    
    400	    if (pszDest) {
       0x00005555556217b9 <+809>:	cmpq   $0x0,-0x340(%rbp)
       0x00005555556217c1 <+817>:	je     0x555555621d13 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2179>
       0x00005555556217c7 <+823>:	lea    -0x368(%rbp),%rdi
    
    401	        std::vector<CService> resolved;
       0x00005555556217ce <+830>:	call   0x5555555ed810 <_ZNSt6vectorI8CServiceSaIS0_EEC2Ev>
    
    402	        if (Lookup(pszDest, resolved,  default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) {
       0x00005555556217d3 <+835>:	mov    -0x340(%rbp),%rsi
       0x00005555556217da <+842>:	lea    -0x370(%rbp),%rax
       0x00005555556217e1 <+849>:	mov    %rax,%rdi
       0x00005555556217e4 <+852>:	mov    %rsi,-0x470(%rbp)
       0x00005555556217eb <+859>:	mov    %rax,-0x478(%rbp)
       0x00005555556217f2 <+866>:	call   0x555555582c40 <_ZNSaIcEC1Ev@plt>
       0x00005555556217f7 <+871>:	lea    -0x70(%rbp),%rdi
       0x00005555556217fb <+875>:	mov    -0x470(%rbp),%rsi
       0x0000555555621802 <+882>:	mov    -0x478(%rbp),%rdx
       0x0000555555621809 <+889>:	call   0x55555559c0c0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC2IS3_EEPKcRKS3_>
       0x000055555562180e <+894>:	jmp    0x555555621813 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+899>
       0x0000555555621813 <+899>:	xor    %eax,%eax
       0x0000555555621815 <+901>:	lea    0xedae88(%rip),%rcx        # 0x5555564fc6a4 <fNameLookup>
       0x000055555562181c <+908>:	mov    -0x3ec(%rbp),%edx
       0x0000555555621822 <+914>:	testb  $0x1,(%rcx)
       0x0000555555621825 <+917>:	mov    %edx,-0x47c(%rbp)
       0x000055555562182b <+923>:	mov    %al,-0x47d(%rbp)
       0x0000555555621831 <+929>:	je     0x555555621855 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+965>
       0x0000555555621837 <+935>:	call   0x555555eb8110 <_Z13HaveNameProxyv>
       0x000055555562183c <+940>:	mov    %al,-0x47e(%rbp)
       0x0000555555621842 <+946>:	jmp    0x555555621847 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+951>
       0x0000555555621847 <+951>:	mov    -0x47e(%rbp),%al
       0x000055555562184d <+957>:	xor    $0xff,%al
       0x000055555562184f <+959>:	mov    %al,-0x47d(%rbp)
       0x0000555555621855 <+965>:	mov    -0x47d(%rbp),%al
       0x000055555562185b <+971>:	movzbl %al,%ecx
       0x000055555562185e <+974>:	and    $0x1,%ecx
       0x0000555555621861 <+977>:	lea    -0x70(%rbp),%rdi
       0x0000555555621865 <+981>:	lea    -0x368(%rbp),%rsi
       0x000055555562186c <+988>:	mov    $0x100,%r8d
       0x0000555555621872 <+994>:	mov    -0x47c(%rbp),%edx
       0x0000555555621878 <+1000>:	call   0x555555eb6560 <_Z6LookupRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt6vectorI8CServiceSaIS8_EEibj>
       0x000055555562187d <+1005>:	mov    %al,-0x47f(%rbp)
       0x0000555555621883 <+1011>:	jmp    0x555555621888 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1016>
    --Type <RET> for more, q to quit, c to continue without paging--
       0x0000555555621888 <+1016>:	xor    %eax,%eax
       0x000055555562188a <+1018>:	mov    -0x47f(%rbp),%cl
       0x0000555555621890 <+1024>:	test   $0x1,%cl
       0x0000555555621893 <+1027>:	mov    %al,-0x480(%rbp)
       0x0000555555621899 <+1033>:	jne    0x5555556218a4 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1044>
       0x000055555562189f <+1039>:	jmp    0x5555556218b8 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1064>
       0x00005555556218a4 <+1044>:	lea    -0x368(%rbp),%rdi
       0x00005555556218ab <+1051>:	call   0x5555555d5830 <_ZNKSt6vectorI8CServiceSaIS0_EE5emptyEv>
       0x00005555556218b0 <+1056>:	xor    $0xff,%al
       0x00005555556218b2 <+1058>:	mov    %al,-0x480(%rbp)
       0x00005555556218b8 <+1064>:	mov    -0x480(%rbp),%al
       0x00005555556218be <+1070>:	lea    -0x70(%rbp),%rdi
       0x00005555556218c2 <+1074>:	mov    %al,-0x481(%rbp)
       0x00005555556218c8 <+1080>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x00005555556218cd <+1085>:	lea    -0x370(%rbp),%rdi
       0x00005555556218d4 <+1092>:	call   0x5555555833a0 <_ZNSaIcED1Ev@plt>
       0x00005555556218d9 <+1097>:	mov    -0x481(%rbp),%al
       0x00005555556218df <+1103>:	test   $0x1,%al
       0x00005555556218e1 <+1105>:	jne    0x5555556218ec <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1116>
       0x00005555556218e7 <+1111>:	jmp    0x555555621ccf <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2111>
       0x00005555556218ec <+1116>:	lea    -0x368(%rbp),%rax
       0x0000555555621a37 <+1447>:	lea    -0x70(%rbp),%rdi
       0x0000555555621a3b <+1451>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x0000555555621a40 <+1456>:	lea    -0x370(%rbp),%rdi
       0x0000555555621a47 <+1463>:	call   0x5555555833a0 <_ZNSaIcED1Ev@plt>
       0x0000555555621a4c <+1468>:	jmp    0x555555621d02 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2162>
    
    403	            addrConnect = CAddress(resolved[GetRand(resolved.size())], NODE_NONE);
       0x00005555556218f3 <+1123>:	mov    %rax,%rdi
       0x00005555556218f6 <+1126>:	mov    %rax,-0x490(%rbp)
       0x00005555556218fd <+1133>:	call   0x5555555d59f0 <_ZNKSt6vectorI8CServiceSaIS0_EE4sizeEv>
       0x0000555555621902 <+1138>:	mov    %rax,%rdi
       0x0000555555621905 <+1141>:	call   0x555555f58ff0 <_Z7GetRandm>
       0x000055555562190a <+1146>:	mov    -0x490(%rbp),%rdi
       0x0000555555621911 <+1153>:	mov    %rax,%rsi
       0x0000555555621914 <+1156>:	call   0x55555563e7c0 <_ZNSt6vectorI8CServiceSaIS0_EEixEm>
       0x0000555555621919 <+1161>:	lea    -0xc8(%rbp),%rdi
       0x0000555555621920 <+1168>:	mov    %rax,%rsi
       0x0000555555621923 <+1171>:	call   0x5555555d5980 <_ZN8CServiceC2ERKS_>
       0x0000555555621928 <+1176>:	jmp    0x55555562192d <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1181>
       0x000055555562192d <+1181>:	xor    %eax,%eax
       0x000055555562192f <+1183>:	mov    %eax,%edx
       0x0000555555621931 <+1185>:	lea    -0xa0(%rbp),%rdi
       0x0000555555621938 <+1192>:	lea    -0xc8(%rbp),%rsi
       0x000055555562193f <+1199>:	call   0x55555563ddb0 <_ZN8CAddressC2E8CService12ServiceFlags>
       0x0000555555621944 <+1204>:	jmp    0x555555621949 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1209>
       0x0000555555621949 <+1209>:	lea    -0xa0(%rbp),%rsi
       0x0000555555621950 <+1216>:	mov    -0x428(%rbp),%rdi
       0x0000555555621957 <+1223>:	call   0x55555563de20 <_ZN8CAddressaSEOS_>
       0x000055555562195c <+1228>:	jmp    0x555555621961 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1233>
       0x0000555555621961 <+1233>:	lea    -0xa0(%rbp),%rdi
       0x0000555555621968 <+1240>:	call   0x55555563de90 <_ZN8CAddressD2Ev>
       0x000055555562196d <+1245>:	lea    -0xc8(%rbp),%rdi
       0x0000555555621974 <+1252>:	call   0x5555555d3b20 <_ZN8CServiceD2Ev>
       0x0000555555621979 <+1257>:	mov    -0x428(%rbp),%rdi
    --Type <RET> for more, q to quit, c to continue without paging--
       0x0000555555621a82 <+1522>:	lea    -0xa0(%rbp),%rdi
       0x0000555555621a89 <+1529>:	call   0x55555563de90 <_ZN8CAddressD2Ev>
       0x0000555555621a8e <+1534>:	lea    -0xc8(%rbp),%rdi
       0x0000555555621a95 <+1541>:	call   0x5555555d3b20 <_ZN8CServiceD2Ev>
       0x0000555555621a9a <+1546>:	jmp    0x555555621d02 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2162>
    
    404	            if (!addrConnect.IsValid()) {
       0x0000555555621980 <+1264>:	call   0x555555eaba70 <_ZNK8CNetAddr7IsValidEv>
       0x0000555555621985 <+1269>:	mov    %al,-0x491(%rbp)
       0x000055555562198b <+1275>:	jmp    0x555555621990 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1280>
       0x0000555555621990 <+1280>:	mov    -0x491(%rbp),%al
       0x0000555555621996 <+1286>:	test   $0x1,%al
       0x0000555555621998 <+1288>:	jne    0x555555621ae1 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1617>
       0x000055555562199e <+1294>:	jmp    0x5555556219a3 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1299>
    
    405	                LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest);
       0x00005555556219a3 <+1299>:	jmp    0x5555556219a8 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1304>
       0x00005555556219a8 <+1304>:	mov    $0x1,%edi
       0x00005555556219ad <+1309>:	call   0x55555561fd20 <_ZL17LogAcceptCategoryN5BCLog8LogFlagsE>
       0x00005555556219b2 <+1314>:	mov    %al,-0x492(%rbp)
       0x00005555556219b8 <+1320>:	jmp    0x5555556219bd <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1325>
       0x00005555556219bd <+1325>:	mov    -0x492(%rbp),%al
       0x00005555556219c3 <+1331>:	test   $0x1,%al
       0x00005555556219c5 <+1333>:	jne    0x5555556219d0 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1344>
       0x00005555556219cb <+1339>:	jmp    0x555555621abd <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1581>
       0x00005555556219d0 <+1344>:	lea    -0xe8(%rbp),%rdi
       0x00005555556219d7 <+1351>:	mov    -0x428(%rbp),%rsi
       0x00005555556219de <+1358>:	call   0x555555eaef60 <_ZNK8CService8ToStringB5cxx11Ev>
       0x00005555556219e3 <+1363>:	jmp    0x5555556219e8 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1368>
       0x00005555556219e8 <+1368>:	lea    0xafb597(%rip),%rdi        # 0x55555611cf86
       0x00005555556219ef <+1375>:	lea    -0xe8(%rbp),%rsi
       0x00005555556219f6 <+1382>:	lea    -0x340(%rbp),%rdx
       0x00005555556219fd <+1389>:	call   0x555555622f20 <_ZL9LogPrintfIJNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPKcEEvS7_DpRKT_>
       0x0000555555621a02 <+1394>:	jmp    0x555555621a07 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1399>
       0x0000555555621a07 <+1399>:	lea    -0xe8(%rbp),%rdi
       0x0000555555621a0e <+1406>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x0000555555621a13 <+1411>:	jmp    0x555555621abd <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1581>
       0x0000555555621aac <+1564>:	lea    -0xe8(%rbp),%rdi
       0x0000555555621ab3 <+1571>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x0000555555621ab8 <+1576>:	jmp    0x555555621d02 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2162>
       0x0000555555621abd <+1581>:	jmp    0x555555621ac2 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1586>
       0x0000555555621ac2 <+1586>:	jmp    0x555555621ac7 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1591>
    
    406	                return nullptr;
       0x0000555555621ac7 <+1591>:	movq   $0x0,-0x3c0(%rbp)
       0x0000555555621ad2 <+1602>:	movl   $0x1,-0x3f0(%rbp)
       0x0000555555621adc <+1612>:	jmp    0x555555621cd9 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2121>
       0x0000555555621ae1 <+1617>:	mov    -0x430(%rbp),%rax
    
    407	            }
    408	            // It is possible that we already have a connection to the IP/port pszDest resolved to.
    409	            // In that case, drop the connection that was just created, and return the existing CNode instead.
    410	            // Also store the name we used to connect in that CNode, so that future FindNode() calls to that
    411	            // name catch this early.
    412	            LOCK(cs_vNodes);
       0x0000555555621ae8 <+1624>:	add    $0x50370,%rax
       0x0000555555621aee <+1630>:	lea    0xafb3be(%rip),%rdx        # 0x55555611ceb3
       0x0000555555621af5 <+1637>:	lea    0xb266d5(%rip),%rcx        # 0x5555561481d1
       0x0000555555621afc <+1644>:	lea    -0x338(%rbp),%rdi
       0x0000555555621b03 <+1651>:	mov    $0x19c,%r8d
       0x0000555555621b09 <+1657>:	xor    %r9d,%r9d
       0x0000555555621b0c <+1660>:	mov    %rax,%rsi
       0x0000555555621b0f <+1663>:	call   0x5555555cd8e0 <_ZN10UniqueLockI14AnnotatedMixinISt15recursive_mutexESt11unique_lockIS1_EEC2ERS2_PKcS8_ib>
       0x0000555555621b14 <+1668>:	jmp    0x555555621b19 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1673>
       0x0000555555621b19 <+1673>:	lea    -0x110(%rbp),%rdi
       0x0000555555621b20 <+1680>:	mov    -0x428(%rbp),%rsi
    
    413	            CNode* pnode = FindNode(static_cast<CService>(addrConnect));
       0x0000555555621b27 <+1687>:	call   0x5555555d5980 <_ZN8CServiceC2ERKS_>
       0x0000555555621b2c <+1692>:	jmp    0x555555621b31 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1697>
       0x0000555555621b31 <+1697>:	lea    -0x110(%rbp),%rsi
       0x0000555555621b38 <+1704>:	mov    -0x430(%rbp),%rdi
       0x0000555555621b3f <+1711>:	call   0x555555620fe0 <_ZN8CConnman8FindNodeERK8CService>
       0x0000555555621b44 <+1716>:	mov    %rax,-0x4a0(%rbp)
       0x0000555555621b4b <+1723>:	jmp    0x555555621b50 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1728>
       0x0000555555621b50 <+1728>:	lea    -0x110(%rbp),%rdi
       0x0000555555621b57 <+1735>:	call   0x5555555d3b20 <_ZN8CServiceD2Ev>
       0x0000555555621b5c <+1740>:	mov    -0x4a0(%rbp),%rax
       0x0000555555621b63 <+1747>:	mov    %rax,-0x3f8(%rbp)
       0x0000555555621c43 <+1971>:	lea    -0x110(%rbp),%rdi
       0x0000555555621c4a <+1978>:	call   0x5555555d3b20 <_ZN8CServiceD2Ev>
       0x0000555555621c4f <+1983>:	jmp    0x555555621cbe <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2094>
    
    414	            if (pnode)
       0x0000555555621b6a <+1754>:	cmpq   $0x0,-0x3f8(%rbp)
       0x0000555555621b72 <+1762>:	je     0x555555621c90 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2048>
    
    415	            {
    416	                pnode->MaybeSetAddrName(std::string(pszDest));
       0x0000555555621b78 <+1768>:	mov    -0x3f8(%rbp),%rdi
       0x0000555555621b7f <+1775>:	mov    -0x340(%rbp),%rsi
       0x0000555555621b86 <+1782>:	lea    -0x378(%rbp),%rax
       0x0000555555621b8d <+1789>:	mov    %rdi,-0x4a8(%rbp)
       0x0000555555621b94 <+1796>:	mov    %rax,%rdi
       0x0000555555621b97 <+1799>:	mov    %rsi,-0x4b0(%rbp)
       0x0000555555621b9e <+1806>:	mov    %rax,-0x4b8(%rbp)
       0x0000555555621ba5 <+1813>:	call   0x555555582c40 <_ZNSaIcEC1Ev@plt>
       0x0000555555621baa <+1818>:	lea    -0x130(%rbp),%rdi
       0x0000555555621bb1 <+1825>:	mov    -0x4b0(%rbp),%rsi
       0x0000555555621bb8 <+1832>:	mov    -0x4b8(%rbp),%rdx
       0x0000555555621bbf <+1839>:	call   0x55555559c0c0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC2IS3_EEPKcRKS3_>
       0x0000555555621bc4 <+1844>:	jmp    0x555555621bc9 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1849>
       0x0000555555621bc9 <+1849>:	lea    -0x130(%rbp),%rsi
       0x0000555555621bd0 <+1856>:	mov    -0x4a8(%rbp),%rdi
       0x0000555555621bd7 <+1863>:	call   0x555555623210 <_ZN5CNode16MaybeSetAddrNameERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE>
       0x0000555555621bdc <+1868>:	jmp    0x555555621be1 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1873>
       0x0000555555621be1 <+1873>:	lea    -0x130(%rbp),%rdi
       0x0000555555621be8 <+1880>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x0000555555621bed <+1885>:	lea    -0x378(%rbp),%rdi
       0x0000555555621bf4 <+1892>:	call   0x5555555833a0 <_ZNSaIcED1Ev@plt>
    --Type <RET> for more, q to quit, c to continue without paging--
       0x0000555555621c73 <+2019>:	lea    -0x130(%rbp),%rdi
       0x0000555555621c7a <+2026>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x0000555555621c7f <+2031>:	lea    -0x378(%rbp),%rdi
       0x0000555555621c86 <+2038>:	call   0x5555555833a0 <_ZNSaIcED1Ev@plt>
       0x0000555555621c8b <+2043>:	jmp    0x555555621cbe <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2094>
    
    417	                LogPrintf("Failed to open new connection, already connected\n");
       0x0000555555621bf9 <+1897>:	lea    0xafb32d(%rip),%rdi        # 0x55555611cf2d
       0x0000555555621c00 <+1904>:	call   0x555555622950 <_ZL9LogPrintfIJEEvPKcDpRKT_>
       0x0000555555621c05 <+1909>:	jmp    0x555555621c0a <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1914>
    
    418	                return nullptr;
       0x0000555555621c0a <+1914>:	movq   $0x0,-0x3c0(%rbp)
       0x0000555555621c15 <+1925>:	movl   $0x1,-0x3f0(%rbp)
       0x0000555555621c1f <+1935>:	jmp    0x555555621c9a <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2058>
    
    419	            }
    420	        }
       0x0000555555621c90 <+2048>:	movl   $0x0,-0x3f0(%rbp)
       0x0000555555621c9a <+2058>:	lea    -0x338(%rbp),%rdi
       0x0000555555621ca1 <+2065>:	call   0x5555555cd9c0 <_ZN10UniqueLockI14AnnotatedMixinISt15recursive_mutexESt11unique_lockIS1_EED2Ev>
       0x0000555555621ca6 <+2070>:	mov    -0x3f0(%rbp),%eax
       0x0000555555621cac <+2076>:	test   %eax,%eax
       0x0000555555621cae <+2078>:	jne    0x555555621cd9 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2121>
       0x0000555555621cb4 <+2084>:	jmp    0x555555621cb9 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2089>
       0x0000555555621cb9 <+2089>:	jmp    0x555555621ccf <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2111>
       0x0000555555621cbe <+2094>:	lea    -0x338(%rbp),%rdi
       0x0000555555621cc5 <+2101>:	call   0x5555555cd9c0 <_ZN10UniqueLockI14AnnotatedMixinISt15recursive_mutexESt11unique_lockIS1_EED2Ev>
       0x0000555555621cca <+2106>:	jmp    0x555555621d02 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2162>
    
    421	    }
       0x0000555555621ccf <+2111>:	movl   $0x0,-0x3f0(%rbp)
       0x0000555555621cd9 <+2121>:	lea    -0x368(%rbp),%rdi
       0x0000555555621ce0 <+2128>:	call   0x5555555efee0 <_ZNSt6vectorI8CServiceSaIS0_EED2Ev>
       0x0000555555621ce5 <+2133>:	mov    -0x3f0(%rbp),%eax
       0x0000555555621ceb <+2139>:	test   %eax,%eax
       0x0000555555621ced <+2141>:	je     0x555555621cfd <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2157>
       0x0000555555621cf3 <+2147>:	jmp    0x555555621cf8 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2152>
       0x0000555555621cf8 <+2152>:	jmp    0x5555556228fd <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5229>
       0x0000555555621cfd <+2157>:	jmp    0x555555621d13 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2179>
       0x0000555555621d02 <+2162>:	lea    -0x368(%rbp),%rdi
       0x0000555555621d09 <+2169>:	call   0x5555555efee0 <_ZNSt6vectorI8CServiceSaIS0_EED2Ev>
       0x0000555555621d0e <+2174>:	jmp    0x555555622931 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5281>
    
    422	
    423	    // Connect
    424	    bool connected = false;
       0x0000555555621d13 <+2179>:	movb   $0x0,-0x3f9(%rbp)
       0x0000555555621d1a <+2186>:	lea    -0x380(%rbp),%rdi
    
    425	    std::unique_ptr<Sock> sock;
       0x0000555555621d21 <+2193>:	call   0x55555563e820 <_ZNSt10unique_ptrI4SockSt14default_deleteIS0_EEC2IS2_vEEv>
       0x0000555555621d26 <+2198>:	lea    -0x160(%rbp),%rdi
    
    426	    proxyType proxy;
       0x0000555555621d2d <+2205>:	call   0x55555563e880 <_ZN9proxyTypeC2Ev>
       0x0000555555621d32 <+2210>:	jmp    0x555555621d37 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2215>
       0x0000555555621d37 <+2215>:	lea    -0x190(%rbp),%rdi
    
    427	    CAddress addr_bind;
       0x0000555555621d3e <+2222>:	call   0x55555563e8e0 <_ZN8CAddressC2Ev>
       0x0000555555621d43 <+2227>:	jmp    0x555555621d48 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2232>
       0x0000555555621d48 <+2232>:	lea    -0x190(%rbp),%rdi
    
    428	    assert(!addr_bind.IsValid());
       0x0000555555621d4f <+2239>:	call   0x555555eaba70 <_ZNK8CNetAddr7IsValidEv>
       0x0000555555621d54 <+2244>:	mov    %al,-0x4b9(%rbp)
       0x0000555555621d5a <+2250>:	jmp    0x555555621d5f <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2255>
       0x0000555555621d5f <+2255>:	mov    -0x4b9(%rbp),%al
       0x0000555555621d65 <+2261>:	xor    $0xff,%al
       0x0000555555621d67 <+2263>:	test   $0x1,%al
       0x0000555555621d69 <+2265>:	jne    0x555555621d74 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2276>
       0x0000555555621d6f <+2271>:	jmp    0x555555621d79 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2281>
       0x0000555555621d74 <+2276>:	jmp    0x555555621dce <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2366>
       0x0000555555621d79 <+2281>:	lea    0xafb233(%rip),%rdi        # 0x55555611cfb3
       0x0000555555621d80 <+2288>:	lea    0xb2644a(%rip),%rsi        # 0x5555561481d1
       0x0000555555621d87 <+2295>:	mov    $0x1ac,%edx
       0x0000555555621d8c <+2300>:	lea    0xafb14f(%rip),%rcx        # 0x55555611cee2
       0x0000555555621d93 <+2307>:	call   0x555555581490 <__assert_fail@plt>
    
    429	
    430	    if (addrConnect.IsValid()) {
    => 0x0000555555621dd5 <+2373>:	call   0x555555eaba70 <_ZNK8CNetAddr7IsValidEv>
       0x0000555555621dda <+2378>:	mov    %al,-0x4ba(%rbp)
       0x0000555555621de0 <+2384>:	jmp    0x555555621de5 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2389>
       0x0000555555621de5 <+2389>:	mov    -0x4ba(%rbp),%al
       0x0000555555621deb <+2395>:	test   $0x1,%al
       0x0000555555621ded <+2397>:	jne    0x555555621df8 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2408>
       0x0000555555621df3 <+2403>:	jmp    0x5555556222e1 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3665>
    
    431	        bool proxyConnectionFailed = false;
       0x0000555555621df8 <+2408>:	movb   $0x0,-0x381(%rbp)
       0x0000555555621dff <+2415>:	mov    -0x428(%rbp),%rdi
    
    432	
    433	        if (addrConnect.GetNetwork() == NET_I2P && m_i2p_sam_session.get() != nullptr) {
       0x0000555555621e06 <+2422>:	call   0x555555eabf20 <_ZNK8CNetAddr10GetNetworkEv>
       0x0000555555621e0b <+2427>:	mov    %eax,-0x4c0(%rbp)
       0x0000555555621e11 <+2433>:	jmp    0x555555621e16 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2438>
       0x0000555555621e16 <+2438>:	mov    -0x4c0(%rbp),%eax
       0x0000555555621e1c <+2444>:	cmp    $0x4,%eax
       0x0000555555621e1f <+2447>:	jne    0x555555621fcf <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2879>
       0x0000555555621e25 <+2453>:	mov    -0x430(%rbp),%rax
       0x0000555555621e2c <+2460>:	add    $0x50518,%rax
       0x0000555555621e32 <+2466>:	mov    %rax,%rdi
       0x0000555555621e35 <+2469>:	call   0x55555563e950 <_ZNKSt10unique_ptrIN3i2p3sam7SessionESt14default_deleteIS2_EE3getEv>
       0x0000555555621e3a <+2474>:	cmp    $0x0,%rax
       0x0000555555621e3e <+2478>:	je     0x555555621fcf <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2879>
       0x0000555555621e44 <+2484>:	lea    -0x1f0(%rbp),%rdi
    
    434	            i2p::Connection conn;
       0x0000555555621e4b <+2491>:	call   0x55555563e9b0 <_ZN3i2p10ConnectionC2Ev>
       0x0000555555621e50 <+2496>:	jmp    0x555555621e55 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2501>
       0x0000555555621e55 <+2501>:	mov    -0x430(%rbp),%rax
    
    435	            if (m_i2p_sam_session->Connect(addrConnect, conn, proxyConnectionFailed)) {
       0x0000555555621e5c <+2508>:	add    $0x50518,%rax
       0x0000555555621e62 <+2514>:	mov    %rax,%rdi
       0x0000555555621e65 <+2517>:	call   0x55555563ea70 <_ZNKSt10unique_ptrIN3i2p3sam7SessionESt14default_deleteIS2_EEptEv>
       0x0000555555621e6a <+2522>:	lea    -0x1f0(%rbp),%rdx
       0x0000555555621e71 <+2529>:	lea    -0x381(%rbp),%rcx
       0x0000555555621e78 <+2536>:	mov    %rax,%rdi
       0x0000555555621e7b <+2539>:	mov    -0x428(%rbp),%rsi
       0x0000555555621e82 <+2546>:	call   0x555555b78370 <_ZN3i2p3sam7Session7ConnectERK8CServiceRNS_10ConnectionERb>
       0x0000555555621e87 <+2551>:	mov    %al,-0x4c1(%rbp)
       0x0000555555621e8d <+2557>:	jmp    0x555555621e92 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2562>
       0x0000555555621e92 <+2562>:	mov    -0x4c1(%rbp),%al
       0x0000555555621e98 <+2568>:	test   $0x1,%al
       0x0000555555621e9a <+2570>:	jne    0x555555621ea5 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2581>
       0x0000555555621ea0 <+2576>:	jmp    0x555555621fad <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2845>
    
    436	                connected = true;
       0x0000555555621ea5 <+2581>:	movb   $0x1,-0x3f9(%rbp)
       0x0000555555621eac <+2588>:	lea    -0x1f0(%rbp),%rdi
    
    437	                *sock = std::move(conn.sock);
       0x0000555555621eb3 <+2595>:	call   0x55555563eac0 <_ZSt4moveIR4SockEONSt16remove_referenceIT_E4typeEOS3_>
       0x0000555555621eb8 <+2600>:	lea    -0x380(%rbp),%rdi
       0x0000555555621ebf <+2607>:	mov    %rax,-0x4d0(%rbp)
       0x0000555555621ec6 <+2614>:	call   0x55555563eb10 <_ZNKSt10unique_ptrI4SockSt14default_deleteIS0_EEdeEv>
       0x0000555555621ecb <+2619>:	mov    %rax,-0x4d8(%rbp)
       0x0000555555621ed2 <+2626>:	jmp    0x555555621ed7 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2631>
       0x0000555555621ed7 <+2631>:	mov    -0x4d8(%rbp),%rax
       0x0000555555621ede <+2638>:	mov    (%rax),%rcx
       0x0000555555621ee1 <+2641>:	mov    0x10(%rcx),%rcx
       0x0000555555621ee5 <+2645>:	mov    %rax,%rdi
       0x0000555555621ee8 <+2648>:	mov    -0x4d0(%rbp),%rsi
       0x0000555555621eef <+2655>:	call   *%rcx
       0x0000555555621ef1 <+2657>:	jmp    0x555555621ef6 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2662>
    
    438	                addr_bind = CAddress{conn.me, NODE_NONE};
       0x0000555555621ef6 <+2662>:	lea    -0x1e0(%rbp),%rsi
       0x0000555555621efd <+2669>:	lea    -0x248(%rbp),%rdi
       0x0000555555621f04 <+2676>:	call   0x5555555d5980 <_ZN8CServiceC2ERKS_>
       0x0000555555621f09 <+2681>:	jmp    0x555555621f0e <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2686>
       0x0000555555621f0e <+2686>:	xor    %eax,%eax
       0x0000555555621f10 <+2688>:	mov    %eax,%edx
       0x0000555555621f12 <+2690>:	lea    -0x220(%rbp),%rdi
       0x0000555555621f19 <+2697>:	lea    -0x248(%rbp),%rsi
       0x0000555555621f20 <+2704>:	call   0x55555563ddb0 <_ZN8CAddressC2E8CService12ServiceFlags>
       0x0000555555621f25 <+2709>:	jmp    0x555555621f2a <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2714>
       0x0000555555621f2a <+2714>:	lea    -0x190(%rbp),%rdi
       0x0000555555621f31 <+2721>:	lea    -0x220(%rbp),%rsi
       0x0000555555621f38 <+2728>:	call   0x55555563de20 <_ZN8CAddressaSEOS_>
       0x0000555555621f3d <+2733>:	jmp    0x555555621f42 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2738>
       0x0000555555621f42 <+2738>:	lea    -0x220(%rbp),%rdi
       0x0000555555621f49 <+2745>:	call   0x55555563de90 <_ZN8CAddressD2Ev>
       0x0000555555621f4e <+2750>:	lea    -0x248(%rbp),%rdi
       0x0000555555621f55 <+2757>:	call   0x5555555d3b20 <_ZN8CServiceD2Ev>
       0x0000555555621f90 <+2816>:	lea    -0x220(%rbp),%rdi
       0x0000555555621f97 <+2823>:	call   0x55555563de90 <_ZN8CAddressD2Ev>
       0x0000555555621f9c <+2828>:	lea    -0x248(%rbp),%rdi
       0x0000555555621fa3 <+2835>:	call   0x5555555d3b20 <_ZN8CServiceD2Ev>
       0x0000555555621fa8 <+2840>:	jmp    0x555555621fbe <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2862>
    
    439	            }
       0x0000555555621f5a <+2762>:	jmp    0x555555621fad <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2845>
    
    440	        } else if (GetProxy(addrConnect.GetNetwork(), proxy)) {
       0x0000555555621fad <+2845>:	lea    -0x1f0(%rbp),%rdi
       0x0000555555621fb4 <+2852>:	call   0x55555563eb60 <_ZN3i2p10ConnectionD2Ev>
       0x0000555555621fb9 <+2857>:	jmp    0x55555562225e <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3534>
       0x0000555555621fbe <+2862>:	lea    -0x1f0(%rbp),%rdi
       0x0000555555621fc5 <+2869>:	call   0x55555563eb60 <_ZN3i2p10ConnectionD2Ev>
       0x0000555555621fca <+2874>:	jmp    0x5555556228d4 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5188>
       0x0000555555621fcf <+2879>:	mov    -0x428(%rbp),%rdi
       0x0000555555621fd6 <+2886>:	call   0x555555eabf20 <_ZNK8CNetAddr10GetNetworkEv>
       0x0000555555621fdb <+2891>:	mov    %eax,-0x4dc(%rbp)
       0x0000555555621fe1 <+2897>:	jmp    0x555555621fe6 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2902>
       0x0000555555621fe6 <+2902>:	lea    -0x160(%rbp),%rsi
       0x0000555555621fed <+2909>:	mov    -0x4dc(%rbp),%edi
       0x0000555555621ff3 <+2915>:	call   0x555555eb7dd0 <_Z8GetProxy7NetworkR9proxyType>
       0x0000555555621ff8 <+2920>:	mov    %al,-0x4dd(%rbp)
       0x0000555555621ffe <+2926>:	jmp    0x555555622003 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2931>
       0x0000555555622003 <+2931>:	mov    -0x4dd(%rbp),%al
       0x0000555555622009 <+2937>:	test   $0x1,%al
       0x000055555562200b <+2939>:	jne    0x555555622016 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2950>
       0x0000555555622011 <+2945>:	jmp    0x55555562215a <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3274>
    
    441	            sock = CreateSock(proxy.proxy);
       0x0000555555622016 <+2950>:	lea    0xee2773(%rip),%rsi        # 0x555556504790 <CreateSock>
       0x000055555562201d <+2957>:	lea    -0x390(%rbp),%rdi
       0x0000555555622024 <+2964>:	lea    -0x160(%rbp),%rdx
       0x000055555562202b <+2971>:	call   0x55555563ebd0 <_ZNKSt8functionIFSt10unique_ptrI4SockSt14default_deleteIS1_EERK8CServiceEEclES7_>
       0x0000555555622030 <+2976>:	jmp    0x555555622035 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2981>
       0x0000555555622035 <+2981>:	lea    -0x380(%rbp),%rdi
       0x000055555562203c <+2988>:	lea    -0x390(%rbp),%rsi
       0x0000555555622043 <+2995>:	call   0x55555563ec80 <_ZNSt10unique_ptrI4SockSt14default_deleteIS0_EEaSEOS3_>
       0x0000555555622048 <+3000>:	lea    -0x390(%rbp),%rdi
       0x000055555562204f <+3007>:	mov    %rax,-0x4e8(%rbp)
       0x0000555555622056 <+3014>:	call   0x55555563ece0 <_ZNSt10unique_ptrI4SockSt14default_deleteIS0_EED2Ev>
    
    442	            if (!sock) {
       0x000055555562205b <+3019>:	lea    -0x380(%rbp),%rdi
       0x0000555555622062 <+3026>:	call   0x55555563ed90 <_ZNKSt10unique_ptrI4SockSt14default_deleteIS0_EEcvbEv>
       0x0000555555622067 <+3031>:	test   $0x1,%al
       0x0000555555622069 <+3033>:	jne    0x555555622089 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3065>
    
    443	                return nullptr;
       0x000055555562206f <+3039>:	movq   $0x0,-0x3c0(%rbp)
    --Type <RET> for more, q to quit, c to continue without paging--
       0x000055555562207a <+3050>:	movl   $0x1,-0x3f0(%rbp)
       0x0000555555622084 <+3060>:	jmp    0x5555556228ab <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5147>
       0x0000555555622089 <+3065>:	lea    -0x268(%rbp),%rdi
       0x0000555555622090 <+3072>:	mov    -0x428(%rbp),%rsi
    
    444	            }
    445	            connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(),
       0x0000555555622097 <+3079>:	call   0x555555eabfc0 <_ZNK8CNetAddr10ToStringIPB5cxx11Ev>
       0x000055555562209c <+3084>:	jmp    0x5555556220a1 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3089>
       0x00005555556220a1 <+3089>:	mov    -0x428(%rbp),%rdi
       0x00005555556220a8 <+3096>:	call   0x555555eae740 <_ZNK8CService7GetPortEv>
       0x00005555556220ad <+3101>:	mov    %ax,-0x4ea(%rbp)
       0x00005555556220b4 <+3108>:	jmp    0x5555556220b9 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3113>
       0x00005555556220b9 <+3113>:	mov    -0x4ea(%rbp),%ax
       0x00005555556220c0 <+3120>:	movzwl %ax,%edx
       0x00005555556220c3 <+3123>:	lea    -0x380(%rbp),%rdi
       0x00005555556220ca <+3130>:	mov    %edx,-0x4f0(%rbp)
       0x000055555562210d <+3197>:	call   0x555555eb8320 <_Z19ConnectThroughProxyRK9proxyTypeRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiRK4SockiRb>
       0x0000555555622112 <+3202>:	mov    %al,-0x4f9(%rbp)
       0x0000555555622118 <+3208>:	jmp    0x55555562211d <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3213>
       0x000055555562211d <+3213>:	mov    -0x4f9(%rbp),%al
       0x0000555555622123 <+3219>:	and    $0x1,%al
       0x0000555555622125 <+3221>:	mov    %al,-0x3f9(%rbp)
       0x000055555562212b <+3227>:	lea    -0x268(%rbp),%rdi
       0x0000555555622132 <+3234>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x0000555555622149 <+3257>:	lea    -0x268(%rbp),%rdi
       0x0000555555622150 <+3264>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x0000555555622155 <+3269>:	jmp    0x5555556228d4 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5188>
    
    446	                                            *sock, nConnectTimeout, proxyConnectionFailed);
       0x00005555556220d0 <+3136>:	call   0x55555563eb10 <_ZNKSt10unique_ptrI4SockSt14default_deleteIS0_EEdeEv>
       0x00005555556220d5 <+3141>:	mov    %rax,-0x4f8(%rbp)
       0x00005555556220dc <+3148>:	jmp    0x5555556220e1 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3153>
       0x00005555556220e1 <+3153>:	lea    0xeda5b8(%rip),%rax        # 0x5555564fc6a0 <nConnectTimeout>
       0x00005555556220e8 <+3160>:	mov    (%rax),%r8d
       0x00005555556220eb <+3163>:	lea    -0x160(%rbp),%rdi
       0x00005555556220f2 <+3170>:	lea    -0x268(%rbp),%rsi
       0x00005555556220f9 <+3177>:	lea    -0x381(%rbp),%r9
       0x0000555555622100 <+3184>:	mov    -0x4f0(%rbp),%edx
       0x0000555555622106 <+3190>:	mov    -0x4f8(%rbp),%rcx
    
    447	        } else {
       0x0000555555622137 <+3239>:	jmp    0x555555622259 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3529>
    
    448	            // no proxy needed (none set for target network)
    449	            sock = CreateSock(addrConnect);
       0x000055555562215a <+3274>:	lea    0xee262f(%rip),%rsi        # 0x555556504790 <CreateSock>
       0x0000555555622161 <+3281>:	lea    -0x398(%rbp),%rdi
       0x0000555555622168 <+3288>:	mov    -0x428(%rbp),%rdx
       0x000055555562216f <+3295>:	call   0x55555563ebd0 <_ZNKSt8functionIFSt10unique_ptrI4SockSt14default_deleteIS1_EERK8CServiceEEclES7_>
       0x0000555555622174 <+3300>:	jmp    0x555555622179 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3305>
       0x0000555555622179 <+3305>:	lea    -0x380(%rbp),%rdi
       0x0000555555622180 <+3312>:	lea    -0x398(%rbp),%rsi
       0x0000555555622187 <+3319>:	call   0x55555563ec80 <_ZNSt10unique_ptrI4SockSt14default_deleteIS0_EEaSEOS3_>
       0x000055555562218c <+3324>:	lea    -0x398(%rbp),%rdi
       0x0000555555622193 <+3331>:	mov    %rax,-0x508(%rbp)
       0x000055555562219a <+3338>:	call   0x55555563ece0 <_ZNSt10unique_ptrI4SockSt14default_deleteIS0_EED2Ev>
    
    450	            if (!sock) {
       0x000055555562219f <+3343>:	lea    -0x380(%rbp),%rdi
       0x00005555556221a6 <+3350>:	call   0x55555563ed90 <_ZNKSt10unique_ptrI4SockSt14default_deleteIS0_EEcvbEv>
       0x00005555556221ab <+3355>:	test   $0x1,%al
       0x00005555556221ad <+3357>:	jne    0x5555556221cd <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3389>
    
    451	                return nullptr;
       0x00005555556221b3 <+3363>:	movq   $0x0,-0x3c0(%rbp)
       0x00005555556221be <+3374>:	movl   $0x1,-0x3f0(%rbp)
       0x00005555556221c8 <+3384>:	jmp    0x5555556228ab <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5147>
       0x00005555556221cd <+3389>:	mov    -0x428(%rbp),%rax
       0x00005555556221d4 <+3396>:	lea    -0x380(%rbp),%rdi
       0x00005555556221db <+3403>:	mov    %rax,-0x510(%rbp)
    
    452	            }
    453	            connected = ConnectSocketDirectly(addrConnect, sock->Get(), nConnectTimeout,
       0x00005555556221e2 <+3410>:	call   0x55555563edf0 <_ZNKSt10unique_ptrI4SockSt14default_deleteIS0_EEptEv>
       0x00005555556221e7 <+3415>:	mov    (%rax),%rcx
       0x00005555556221ea <+3418>:	mov    0x18(%rcx),%rcx
       0x00005555556221ee <+3422>:	mov    %rax,%rdi
       0x00005555556221f1 <+3425>:	call   *%rcx
       0x00005555556221f3 <+3427>:	mov    %eax,-0x514(%rbp)
       0x00005555556221f9 <+3433>:	jmp    0x5555556221fe <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3438>
       0x00005555556221fe <+3438>:	mov    -0x514(%rbp),%eax
       0x0000555555622204 <+3444>:	mov    %eax,-0x39c(%rbp)
       0x000055555562220a <+3450>:	lea    0xeda48f(%rip),%rcx        # 0x5555564fc6a0 <nConnectTimeout>
       0x0000555555622211 <+3457>:	mov    (%rcx),%edx
       0x0000555555622220 <+3472>:	movzbl %dil,%ecx
       0x0000555555622224 <+3476>:	lea    -0x39c(%rbp),%r8
       0x000055555562222b <+3483>:	mov    -0x510(%rbp),%rdi
       0x0000555555622232 <+3490>:	mov    %esi,-0x518(%rbp)
       0x0000555555622238 <+3496>:	mov    %r8,%rsi
       0x000055555562223b <+3499>:	call   0x555555eb71f0 <_Z21ConnectSocketDirectlyRK8CServiceRKjib>
       0x0000555555622240 <+3504>:	mov    %al,-0x519(%rbp)
       0x0000555555622246 <+3510>:	jmp    0x55555562224b <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3515>
       0x000055555562224b <+3515>:	mov    -0x519(%rbp),%al
       0x0000555555622251 <+3521>:	and    $0x1,%al
       0x0000555555622253 <+3523>:	mov    %al,-0x3f9(%rbp)
       0x0000555555622259 <+3529>:	jmp    0x55555562225e <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3534>
    
    454	                                              conn_type == ConnectionType::MANUAL);
       0x0000555555622213 <+3459>:	mov    -0x3d0(%rbp),%esi
       0x0000555555622219 <+3465>:	sub    $0x2,%esi
       0x000055555562221c <+3468>:	sete   %dil
    
    455	        }
    456	        if (!proxyConnectionFailed) {
       0x000055555562225e <+3534>:	testb  $0x1,-0x381(%rbp)
       0x0000555555622265 <+3541>:	jne    0x5555556222dc <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3660>
       0x000055555562226b <+3547>:	mov    -0x430(%rbp),%rax
    
    457	            // If a connection to the node was attempted, and failure (if any) is not caused by a problem connecting to
    --Type <RET> for more, q to quit, c to continue without paging--
    458	            // the proxy, mark this as an attempt.
    459	            addrman.Attempt(addrConnect, fCountFailure);
       0x0000555555622272 <+3554>:	add    $0xc0,%rax
       0x0000555555622278 <+3560>:	mov    -0x428(%rbp),%rcx
       0x000055555562227f <+3567>:	mov    -0x3c9(%rbp),%dl
       0x0000555555622285 <+3573>:	mov    %rax,-0x528(%rbp)
       0x000055555562228c <+3580>:	mov    %rcx,-0x530(%rbp)
       0x0000555555622293 <+3587>:	mov    %dl,-0x531(%rbp)
       0x0000555555622299 <+3593>:	call   0x5555559d35f0 <_Z15GetAdjustedTimev>
       0x000055555562229e <+3598>:	mov    %rax,-0x540(%rbp)
       0x00005555556222a5 <+3605>:	jmp    0x5555556222aa <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3610>
       0x00005555556222aa <+3610>:	mov    -0x531(%rbp),%al
       0x00005555556222b0 <+3616>:	movzbl %al,%ecx
       0x00005555556222b3 <+3619>:	and    $0x1,%ecx
       0x00005555556222b6 <+3622>:	mov    -0x528(%rbp),%rdi
       0x00005555556222bd <+3629>:	mov    -0x530(%rbp),%rsi
       0x00005555556222c4 <+3636>:	mov    %ecx,%edx
       0x00005555556222c6 <+3638>:	mov    -0x540(%rbp),%rcx
       0x00005555556222cd <+3645>:	call   0x55555563ee40 <_ZN8CAddrMan7AttemptERK8CServicebl>
       0x00005555556222d2 <+3650>:	jmp    0x5555556222d7 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3655>
    
    460	        }
       0x00005555556222d7 <+3655>:	jmp    0x5555556222dc <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3660>
    
    461	    } else if (pszDest && GetNameProxy(proxy)) {
       0x00005555556222dc <+3660>:	jmp    0x5555556224fc <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4204>
       0x00005555556222e1 <+3665>:	cmpq   $0x0,-0x340(%rbp)
       0x00005555556222e9 <+3673>:	je     0x5555556224f7 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4199>
       0x00005555556222ef <+3679>:	lea    -0x160(%rbp),%rdi
       0x00005555556222f6 <+3686>:	call   0x555555eb8020 <_Z12GetNameProxyR9proxyType>
       0x00005555556222fb <+3691>:	mov    %al,-0x541(%rbp)
       0x0000555555622301 <+3697>:	jmp    0x555555622306 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3702>
       0x0000555555622306 <+3702>:	mov    -0x541(%rbp),%al
       0x000055555562230c <+3708>:	test   $0x1,%al
       0x000055555562230e <+3710>:	jne    0x555555622319 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3721>
       0x0000555555622314 <+3716>:	jmp    0x5555556224f7 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4199>
    
    462	        sock = CreateSock(proxy.proxy);
       0x0000555555622319 <+3721>:	lea    0xee2470(%rip),%rsi        # 0x555556504790 <CreateSock>
       0x0000555555622320 <+3728>:	lea    -0x3a8(%rbp),%rdi
       0x0000555555622327 <+3735>:	lea    -0x160(%rbp),%rdx
       0x000055555562232e <+3742>:	call   0x55555563ebd0 <_ZNKSt8functionIFSt10unique_ptrI4SockSt14default_deleteIS1_EERK8CServiceEEclES7_>
       0x0000555555622333 <+3747>:	jmp    0x555555622338 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3752>
       0x0000555555622338 <+3752>:	lea    -0x380(%rbp),%rdi
       0x000055555562233f <+3759>:	lea    -0x3a8(%rbp),%rsi
       0x0000555555622346 <+3766>:	call   0x55555563ec80 <_ZNSt10unique_ptrI4SockSt14default_deleteIS0_EEaSEOS3_>
       0x000055555562234b <+3771>:	lea    -0x3a8(%rbp),%rdi
       0x0000555555622352 <+3778>:	mov    %rax,-0x550(%rbp)
       0x0000555555622359 <+3785>:	call   0x55555563ece0 <_ZNSt10unique_ptrI4SockSt14default_deleteIS0_EED2Ev>
    
    463	        if (!sock) {
       0x000055555562235e <+3790>:	lea    -0x380(%rbp),%rdi
       0x0000555555622365 <+3797>:	call   0x55555563ed90 <_ZNKSt10unique_ptrI4SockSt14default_deleteIS0_EEcvbEv>
       0x000055555562236a <+3802>:	test   $0x1,%al
       0x000055555562236c <+3804>:	jne    0x55555562238c <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3836>
    
    464	            return nullptr;
       0x0000555555622372 <+3810>:	movq   $0x0,-0x3c0(%rbp)
       0x000055555562237d <+3821>:	movl   $0x1,-0x3f0(%rbp)
       0x0000555555622387 <+3831>:	jmp    0x5555556228ab <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5147>
       0x000055555562238c <+3836>:	lea    -0x288(%rbp),%rdi
    
    465	        }
    466	        std::string host;
       0x0000555555622393 <+3843>:	call   0x555555581920 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1Ev@plt>
    
    467	        int port = default_port;
       0x0000555555622398 <+3848>:	mov    -0x3ec(%rbp),%eax
       0x000055555562239e <+3854>:	mov    %eax,-0x3ac(%rbp)
    
    468	        SplitHostPort(std::string(pszDest), port, host);
       0x00005555556223a4 <+3860>:	mov    -0x340(%rbp),%rsi
       0x00005555556223ab <+3867>:	lea    -0x3b0(%rbp),%rcx
       0x00005555556223b2 <+3874>:	mov    %rcx,%rdi
       0x00005555556223b5 <+3877>:	mov    %rsi,-0x558(%rbp)
       0x00005555556223bc <+3884>:	mov    %rcx,-0x560(%rbp)
       0x00005555556223c3 <+3891>:	call   0x555555582c40 <_ZNSaIcEC1Ev@plt>
       0x00005555556223c8 <+3896>:	lea    -0x2a8(%rbp),%rdi
       0x00005555556223cf <+3903>:	mov    -0x558(%rbp),%rsi
       0x00005555556223d6 <+3910>:	mov    -0x560(%rbp),%rdx
       0x00005555556223dd <+3917>:	call   0x55555559c0c0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC2IS3_EEPKcRKS3_>
       0x00005555556223e2 <+3922>:	jmp    0x5555556223e7 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3927>
       0x00005555556223e7 <+3927>:	lea    -0x2a8(%rbp),%rdi
       0x00005555556223ee <+3934>:	lea    -0x3ac(%rbp),%rsi
       0x00005555556223f5 <+3941>:	lea    -0x288(%rbp),%rdx
       0x00005555556223fc <+3948>:	call   0x555555fa7de0 <_Z13SplitHostPortNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERiRS4_>
       0x0000555555622401 <+3953>:	jmp    0x555555622406 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+3958>
       0x0000555555622406 <+3958>:	lea    -0x2a8(%rbp),%rdi
       0x000055555562240d <+3965>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x0000555555622412 <+3970>:	lea    -0x3b0(%rbp),%rdi
       0x0000555555622419 <+3977>:	call   0x5555555833a0 <_ZNSaIcED1Ev@plt>
       0x00005555556224bc <+4140>:	lea    -0x2a8(%rbp),%rdi
       0x00005555556224c3 <+4147>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x00005555556224c8 <+4152>:	lea    -0x3b0(%rbp),%rdi
       0x00005555556224cf <+4159>:	call   0x5555555833a0 <_ZNSaIcED1Ev@plt>
       0x00005555556224d4 <+4164>:	jmp    0x5555556224e6 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4182>
    
    469	        bool proxyConnectionFailed;
    470	        connected = ConnectThroughProxy(proxy, host, port, *sock, nConnectTimeout,
       0x000055555562241e <+3982>:	mov    -0x3ac(%rbp),%edx
       0x0000555555622424 <+3988>:	lea    -0x380(%rbp),%rdi
       0x000055555562242b <+3995>:	mov    %edx,-0x564(%rbp)
       0x0000555555622431 <+4001>:	call   0x55555563eb10 <_ZNKSt10unique_ptrI4SockSt14default_deleteIS0_EEdeEv>
       0x0000555555622436 <+4006>:	mov    %rax,-0x570(%rbp)
       0x000055555562243d <+4013>:	jmp    0x555555622442 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4018>
       0x0000555555622442 <+4018>:	lea    0xeda257(%rip),%rax        # 0x5555564fc6a0 <nConnectTimeout>
       0x0000555555622449 <+4025>:	mov    (%rax),%r8d
       0x000055555562244c <+4028>:	lea    -0x160(%rbp),%rdi
       0x0000555555622453 <+4035>:	lea    -0x288(%rbp),%rsi
       0x000055555562245a <+4042>:	lea    -0x3b1(%rbp),%r9
       0x0000555555622461 <+4049>:	mov    -0x564(%rbp),%edx
       0x0000555555622467 <+4055>:	mov    -0x570(%rbp),%rcx
       0x000055555562246e <+4062>:	call   0x555555eb8320 <_Z19ConnectThroughProxyRK9proxyTypeRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiRK4SockiRb>
       0x0000555555622473 <+4067>:	mov    %al,-0x571(%rbp)
       0x0000555555622479 <+4073>:	jmp    0x55555562247e <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4078>
       0x000055555562247e <+4078>:	mov    -0x571(%rbp),%al
       0x0000555555622484 <+4084>:	and    $0x1,%al
       0x0000555555622486 <+4086>:	mov    %al,-0x3f9(%rbp)
    
    471	                                        proxyConnectionFailed);
    472	    }
       0x000055555562248c <+4092>:	lea    -0x288(%rbp),%rdi
       0x0000555555622493 <+4099>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x0000555555622498 <+4104>:	jmp    0x5555556224f7 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4199>
       0x00005555556224e6 <+4182>:	lea    -0x288(%rbp),%rdi
       0x00005555556224ed <+4189>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x00005555556224f2 <+4194>:	jmp    0x5555556228d4 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5188>
       0x00005555556224f7 <+4199>:	jmp    0x5555556224fc <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4204>
    
    473	    if (!connected) {
       0x00005555556224fc <+4204>:	testb  $0x1,-0x3f9(%rbp)
       0x0000555555622503 <+4211>:	jne    0x555555622523 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4243>
    
    474	        return nullptr;
       0x0000555555622509 <+4217>:	movq   $0x0,-0x3c0(%rbp)
       0x0000555555622514 <+4228>:	movl   $0x1,-0x3f0(%rbp)
       0x000055555562251e <+4238>:	jmp    0x5555556228ab <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5147>
       0x0000555555622523 <+4243>:	mov    -0x430(%rbp),%rdi
    
    475	    }
    476	
    477	    // Add node
    478	    NodeId id = GetNewNodeId();
       0x000055555562252a <+4250>:	call   0x5555556232f0 <_ZN8CConnman12GetNewNodeIdEv>
       0x000055555562252f <+4255>:	mov    %rax,-0x580(%rbp)
       0x0000555555622536 <+4262>:	jmp    0x55555562253b <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4267>
       0x000055555562253b <+4267>:	mov    -0x580(%rbp),%rax
       0x0000555555622542 <+4274>:	mov    %rax,-0x408(%rbp)
       0x0000555555622549 <+4281>:	lea    -0x2d8(%rbp),%rdi
       0x0000555555622550 <+4288>:	movabs $0xd93e69e2bbfa5735,%rdx
       0x000055555562255a <+4298>:	mov    -0x430(%rbp),%rsi
    
    479	    uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
       0x0000555555622561 <+4305>:	call   0x555555623400 <_ZNK8CConnman26GetDeterministicRandomizerEm>
       0x0000555555622566 <+4310>:	jmp    0x55555562256b <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4315>
       0x000055555562256b <+4315>:	mov    -0x408(%rbp),%rsi
       0x0000555555622572 <+4322>:	lea    -0x2d8(%rbp),%rdi
       0x0000555555622579 <+4329>:	call   0x55555601ba30 <_ZN10CSipHasher5WriteEm>
       0x000055555562257e <+4334>:	mov    %rax,-0x588(%rbp)
       0x0000555555622585 <+4341>:	jmp    0x55555562258a <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4346>
       0x000055555562258a <+4346>:	mov    -0x588(%rbp),%rdi
       0x0000555555622591 <+4353>:	call   0x55555601c070 <_ZNK10CSipHasher8FinalizeEv>
       0x0000555555622596 <+4358>:	mov    %rax,-0x590(%rbp)
       0x000055555562259d <+4365>:	jmp    0x5555556225a2 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4370>
       0x00005555556225a2 <+4370>:	mov    -0x590(%rbp),%rax
    --Type <RET> for more, q to quit, c to continue without paging--
       0x00005555556225a9 <+4377>:	mov    %rax,-0x410(%rbp)
       0x00005555556225b0 <+4384>:	lea    -0x190(%rbp),%rdi
    
    480	    if (!addr_bind.IsValid()) {
       0x00005555556225b7 <+4391>:	call   0x555555eaba70 <_ZNK8CNetAddr7IsValidEv>
       0x00005555556225bc <+4396>:	mov    %al,-0x591(%rbp)
       0x00005555556225c2 <+4402>:	jmp    0x5555556225c7 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4407>
       0x00005555556225c7 <+4407>:	mov    -0x591(%rbp),%al
       0x00005555556225cd <+4413>:	test   $0x1,%al
       0x00005555556225cf <+4415>:	jne    0x55555562265b <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4555>
       0x00005555556225d5 <+4421>:	jmp    0x5555556225da <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4426>
       0x00005555556225da <+4426>:	lea    -0x380(%rbp),%rdi
    
    481	        addr_bind = GetBindAddress(sock->Get());
       0x00005555556225e1 <+4433>:	call   0x55555563edf0 <_ZNKSt10unique_ptrI4SockSt14default_deleteIS0_EEptEv>
       0x00005555556225e6 <+4438>:	mov    (%rax),%rcx
       0x00005555556225e9 <+4441>:	mov    0x18(%rcx),%rcx
       0x00005555556225ed <+4445>:	mov    %rax,%rdi
       0x00005555556225f0 <+4448>:	call   *%rcx
       0x00005555556225f2 <+4450>:	mov    %eax,-0x598(%rbp)
       0x00005555556225f8 <+4456>:	jmp    0x5555556225fd <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4461>
       0x00005555556225fd <+4461>:	lea    -0x308(%rbp),%rdi
       0x0000555555622604 <+4468>:	mov    -0x598(%rbp),%esi
       0x000055555562260a <+4474>:	call   0x5555556234a0 <_ZL14GetBindAddressj>
       0x000055555562260f <+4479>:	jmp    0x555555622614 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4484>
       0x0000555555622614 <+4484>:	lea    -0x190(%rbp),%rdi
       0x000055555562261b <+4491>:	lea    -0x308(%rbp),%rsi
       0x0000555555622622 <+4498>:	call   0x55555563de20 <_ZN8CAddressaSEOS_>
       0x0000555555622627 <+4503>:	jmp    0x55555562262c <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4508>
       0x000055555562262c <+4508>:	lea    -0x308(%rbp),%rdi
       0x0000555555622633 <+4515>:	call   0x55555563de90 <_ZN8CAddressD2Ev>
       0x000055555562264a <+4538>:	lea    -0x308(%rbp),%rdi
       0x0000555555622651 <+4545>:	call   0x55555563de90 <_ZN8CAddressD2Ev>
       0x0000555555622656 <+4550>:	jmp    0x5555556228d4 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5188>
       0x000055555562265b <+4555>:	mov    $0x430,%edi
    
    482	    }
       0x0000555555622638 <+4520>:	jmp    0x55555562265b <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4555>
    
    483	    CNode* pnode = new CNode(id, nLocalServices, sock->Release(), addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", conn_type);
       0x0000555555622660 <+4560>:	call   0x555555581420 <_Znwm@plt>
       0x0000555555622665 <+4565>:	mov    %rax,-0x5a0(%rbp)
       0x000055555562266c <+4572>:	jmp    0x555555622671 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4577>
       0x0000555555622671 <+4577>:	movb   $0x1,-0x419(%rbp)
       0x0000555555622678 <+4584>:	mov    -0x5a0(%rbp),%rax
       0x000055555562267f <+4591>:	mov    -0x408(%rbp),%rsi
       0x0000555555622686 <+4598>:	mov    -0x430(%rbp),%rcx
       0x000055555562268d <+4605>:	mov    0x503d8(%rcx),%rdx
       0x0000555555622694 <+4612>:	lea    -0x380(%rbp),%rdi
       0x000055555562269b <+4619>:	mov    %rax,-0x5a8(%rbp)
       0x00005555556226a2 <+4626>:	mov    %rsi,-0x5b0(%rbp)
       0x00005555556226a9 <+4633>:	mov    %rdx,-0x5b8(%rbp)
       0x00005555556226b0 <+4640>:	call   0x55555563edf0 <_ZNKSt10unique_ptrI4SockSt14default_deleteIS0_EEptEv>
       0x00005555556226b5 <+4645>:	mov    (%rax),%rcx
    --Type <RET> for more, q to quit, c to continue without paging--
       0x00005555556226b8 <+4648>:	mov    0x20(%rcx),%rcx
       0x00005555556226bc <+4652>:	mov    %rax,%rdi
       0x00005555556226bf <+4655>:	call   *%rcx
       0x00005555556226c1 <+4657>:	mov    %eax,-0x5bc(%rbp)
       0x00005555556226c7 <+4663>:	jmp    0x5555556226cc <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4668>
       0x00005555556226cc <+4668>:	mov    -0x430(%rbp),%rdi
       0x00005555556226d3 <+4675>:	mov    -0x428(%rbp),%rsi
       0x00005555556226da <+4682>:	call   0x555555623610 <_ZNK8CConnman22CalculateKeyedNetGroupERK8CAddress>
       0x00005555556226df <+4687>:	mov    %rax,-0x5c8(%rbp)
       0x00005555556226e6 <+4694>:	jmp    0x5555556226eb <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4699>
       0x00005555556226eb <+4699>:	mov    -0x410(%rbp),%rax
       0x00005555556226f2 <+4706>:	cmpq   $0x0,-0x340(%rbp)
       0x00005555556226fa <+4714>:	mov    %rax,-0x5d0(%rbp)
       0x0000555555622701 <+4721>:	je     0x55555562271a <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4746>
       0x0000555555622707 <+4727>:	mov    -0x340(%rbp),%rax
       0x000055555562270e <+4734>:	mov    %rax,-0x5d8(%rbp)
       0x0000555555622715 <+4741>:	jmp    0x55555562272d <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4765>
       0x000055555562271a <+4746>:	lea    0xb5c546(%rip),%rax        # 0x55555617ec67
       0x0000555555622721 <+4753>:	mov    %rax,-0x5d8(%rbp)
       0x0000555555622728 <+4760>:	jmp    0x55555562272d <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4765>
       0x000055555562272d <+4765>:	mov    -0x5d8(%rbp),%rax
       0x0000555555622734 <+4772>:	lea    -0x3b8(%rbp),%rcx
       0x000055555562273b <+4779>:	mov    %rcx,%rdi
       0x000055555562273e <+4782>:	mov    %rax,-0x5e0(%rbp)
       0x0000555555622745 <+4789>:	mov    %rcx,-0x5e8(%rbp)
       0x000055555562274c <+4796>:	call   0x555555582c40 <_ZNSaIcEC1Ev@plt>
       0x0000555555622751 <+4801>:	lea    -0x328(%rbp),%rdi
       0x0000555555622758 <+4808>:	mov    -0x5e0(%rbp),%rsi
       0x000055555562275f <+4815>:	mov    -0x5e8(%rbp),%rdx
       0x0000555555622766 <+4822>:	call   0x55555559c0c0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC2IS3_EEPKcRKS3_>
       0x000055555562276b <+4827>:	jmp    0x555555622770 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4832>
       0x0000555555622770 <+4832>:	mov    -0x3d0(%rbp),%eax
       0x0000555555622776 <+4838>:	mov    %rsp,%rcx
       0x0000555555622779 <+4841>:	mov    %eax,0x18(%rcx)
       0x000055555562277c <+4844>:	lea    -0x328(%rbp),%rdx
       0x0000555555622783 <+4851>:	mov    %rdx,0x10(%rcx)
       0x0000555555622787 <+4855>:	lea    -0x190(%rbp),%rdx
       0x000055555562278e <+4862>:	mov    %rdx,0x8(%rcx)
       0x0000555555622792 <+4866>:	mov    -0x5d0(%rbp),%rdx
       0x0000555555622799 <+4873>:	mov    %rdx,(%rcx)
       0x000055555562279c <+4876>:	movl   $0x0,0x20(%rcx)
       0x00005555556227a3 <+4883>:	mov    -0x5a8(%rbp),%rdi
       0x00005555556227aa <+4890>:	mov    -0x5b0(%rbp),%rsi
       0x00005555556227b1 <+4897>:	mov    -0x5b8(%rbp),%rdx
       0x00005555556227b8 <+4904>:	mov    -0x5bc(%rbp),%ecx
       0x00005555556227be <+4910>:	mov    -0x428(%rbp),%r8
       0x00005555556227c5 <+4917>:	mov    -0x5c8(%rbp),%r9
       0x00005555556227cc <+4924>:	call   0x5555556388d0 <_ZN5CNodeC2El12ServiceFlagsjRK8CAddressmmS3_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE14ConnectionTypeb>
       0x00005555556227d1 <+4929>:	jmp    0x5555556227d6 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4934>
       0x00005555556227d6 <+4934>:	movb   $0x0,-0x419(%rbp)
       0x00005555556227dd <+4941>:	lea    -0x328(%rbp),%rdi
       0x00005555556227e4 <+4948>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x00005555556227e9 <+4953>:	lea    -0x3b8(%rbp),%rdi
       0x00005555556227f0 <+4960>:	call   0x5555555833a0 <_ZNSaIcED1Ev@plt>
       0x00005555556227f5 <+4965>:	mov    -0x5a8(%rbp),%rax
       0x00005555556227fc <+4972>:	mov    %rax,-0x418(%rbp)
       0x0000555555622870 <+5088>:	lea    -0x328(%rbp),%rdi
       0x0000555555622877 <+5095>:	call   0x5555555833d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
       0x000055555562287c <+5100>:	lea    -0x3b8(%rbp),%rdi
       0x0000555555622883 <+5107>:	call   0x5555555833a0 <_ZNSaIcED1Ev@plt>
       0x0000555555622888 <+5112>:	testb  $0x1,-0x419(%rbp)
       0x000055555562288f <+5119>:	jne    0x55555562289a <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5130>
       0x0000555555622895 <+5125>:	jmp    0x5555556228a6 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5142>
       0x000055555562289a <+5130>:	mov    -0x5a0(%rbp),%rdi
       0x00005555556228a1 <+5137>:	call   0x555555581f10 <_ZdlPv@plt>
       0x00005555556228a6 <+5142>:	jmp    0x5555556228d4 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5188>
    
    484	    pnode->AddRef();
       0x0000555555622803 <+4979>:	mov    -0x418(%rbp),%rdi
       0x000055555562280a <+4986>:	call   0x55555563ef20 <_ZN5CNode6AddRefEv>
       0x000055555562280f <+4991>:	jmp    0x555555622814 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4996>
    
    485	
    486	    // We're making a new connection, harvest entropy from the time (and our peer count)
    487	    RandAddEvent((uint32_t)id);
       0x0000555555622814 <+4996>:	mov    -0x408(%rbp),%rax
       0x000055555562281b <+5003>:	mov    %eax,%edi
       0x000055555562281d <+5005>:	call   0x555555f58da0 <_Z12RandAddEventj>
    
    488	
    489	    return pnode;
       0x0000555555622822 <+5010>:	mov    -0x418(%rbp),%rcx
       0x0000555555622829 <+5017>:	mov    %rcx,-0x3c0(%rbp)
       0x0000555555622830 <+5024>:	movl   $0x1,-0x3f0(%rbp)
       0x000055555562283a <+5034>:	jmp    0x5555556228ab <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5147>
    
    490	}
       0x00005555556215c4 <+308>:	mov    %rax,-0x3e0(%rbp)
       0x00005555556215cb <+315>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621756 <+710>:	mov    %rax,-0x3e0(%rbp)
       0x000055555562175d <+717>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621763 <+723>:	jmp    0x55555562177e <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+750>
       0x0000555555621768 <+728>:	mov    %rax,-0x3e0(%rbp)
       0x000055555562176f <+735>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621a18 <+1416>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621a1f <+1423>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621a25 <+1429>:	jmp    0x555555621a40 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1456>
       0x0000555555621a2a <+1434>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621a31 <+1441>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621a51 <+1473>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621a58 <+1480>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621a5e <+1486>:	jmp    0x555555621d02 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2162>
       0x0000555555621a63 <+1491>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621a6a <+1498>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621a70 <+1504>:	jmp    0x555555621a8e <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+1534>
       0x0000555555621a75 <+1509>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621a7c <+1516>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621a9f <+1551>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621aa6 <+1558>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621c24 <+1940>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621c2b <+1947>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621c31 <+1953>:	jmp    0x555555621cbe <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2094>
       0x0000555555621c36 <+1958>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621c3d <+1965>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621c54 <+1988>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621c5b <+1995>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621c61 <+2001>:	jmp    0x555555621c7f <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2031>
       0x0000555555621c66 <+2006>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621c6d <+2013>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621d98 <+2312>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621d9f <+2319>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621da5 <+2325>:	jmp    0x5555556228ec <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5212>
       0x0000555555621daa <+2330>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621db1 <+2337>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621db7 <+2343>:	jmp    0x5555556228e0 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5200>
       0x0000555555621dbc <+2348>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621dc3 <+2355>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621dc9 <+2361>:	jmp    0x5555556228d4 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5188>
       0x0000555555621dce <+2366>:	mov    -0x428(%rbp),%rdi
       0x0000555555621f5f <+2767>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621f66 <+2774>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621f6c <+2780>:	jmp    0x555555621fbe <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2862>
       0x0000555555621f71 <+2785>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621f78 <+2792>:	mov    %edx,-0x3e4(%rbp)
       0x0000555555621f7e <+2798>:	jmp    0x555555621f9c <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+2828>
       0x0000555555621f83 <+2803>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555621f8a <+2810>:	mov    %edx,-0x3e4(%rbp)
       0x000055555562213c <+3244>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555622143 <+3251>:	mov    %edx,-0x3e4(%rbp)
       0x000055555562249d <+4109>:	mov    %rax,-0x3e0(%rbp)
       0x00005555556224a4 <+4116>:	mov    %edx,-0x3e4(%rbp)
       0x00005555556224aa <+4122>:	jmp    0x5555556224c8 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+4152>
       0x00005555556224af <+4127>:	mov    %rax,-0x3e0(%rbp)
       0x00005555556224b6 <+4134>:	mov    %edx,-0x3e4(%rbp)
       0x00005555556224d9 <+4169>:	mov    %rax,-0x3e0(%rbp)
       0x00005555556224e0 <+4176>:	mov    %edx,-0x3e4(%rbp)
       0x000055555562263d <+4525>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555622644 <+4532>:	mov    %edx,-0x3e4(%rbp)
       0x000055555562283f <+5039>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555622846 <+5046>:	mov    %edx,-0x3e4(%rbp)
       0x000055555562284c <+5052>:	jmp    0x555555622888 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5112>
       0x0000555555622851 <+5057>:	mov    %rax,-0x3e0(%rbp)
       0x0000555555622858 <+5064>:	mov    %edx,-0x3e4(%rbp)
       0x000055555562285e <+5070>:	jmp    0x55555562287c <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5100>
       0x0000555555622863 <+5075>:	mov    %rax,-0x3e0(%rbp)
       0x000055555562286a <+5082>:	mov    %edx,-0x3e4(%rbp)
       0x00005555556228ab <+5147>:	lea    -0x190(%rbp),%rdi
       0x00005555556228b2 <+5154>:	call   0x55555563de90 <_ZN8CAddressD2Ev>
       0x00005555556228b7 <+5159>:	lea    -0x160(%rbp),%rdi
       0x00005555556228be <+5166>:	call   0x5555555d3ad0 <_ZN9proxyTypeD2Ev>
       0x00005555556228c3 <+5171>:	lea    -0x380(%rbp),%rdi
       0x00005555556228ca <+5178>:	call   0x55555563ece0 <_ZNSt10unique_ptrI4SockSt14default_deleteIS0_EED2Ev>
       0x00005555556228cf <+5183>:	jmp    0x5555556228fd <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5229>
       0x00005555556228d4 <+5188>:	lea    -0x190(%rbp),%rdi
    --Type <RET> for more, q to quit, c to continue without paging--
       0x00005555556228db <+5195>:	call   0x55555563de90 <_ZN8CAddressD2Ev>
       0x00005555556228e0 <+5200>:	lea    -0x160(%rbp),%rdi
       0x00005555556228e7 <+5207>:	call   0x5555555d3ad0 <_ZN9proxyTypeD2Ev>
       0x00005555556228ec <+5212>:	lea    -0x380(%rbp),%rdi
       0x00005555556228f3 <+5219>:	call   0x55555563ece0 <_ZNSt10unique_ptrI4SockSt14default_deleteIS0_EED2Ev>
       0x00005555556228f8 <+5224>:	jmp    0x555555622931 <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5281>
       0x00005555556228fd <+5229>:	mov    -0x3c0(%rbp),%rax
       0x0000555555622904 <+5236>:	mov    %fs:0x28,%rcx
       0x000055555562290d <+5245>:	mov    -0x8(%rbp),%rdx
       0x0000555555622911 <+5249>:	cmp    %rdx,%rcx
       0x0000555555622914 <+5252>:	mov    %rax,-0x5f0(%rbp)
       0x000055555562291b <+5259>:	jne    0x55555562293d <_ZN8CConnman11ConnectNodeE8CAddressPKcb14ConnectionType+5293>
       0x0000555555622921 <+5265>:	mov    -0x5f0(%rbp),%rax
       0x0000555555622928 <+5272>:	add    $0x620,%rsp
       0x000055555562292f <+5279>:	pop    %rbp
       0x0000555555622930 <+5280>:	ret    
    
    End of assembler dump.
    (gdb) 
    

    </p></details>

  101. in src/net.cpp:437 in a456bd3f29 outdated
     433 | -        if (GetProxy(addrConnect.GetNetwork(), proxy)) {
     434 | +        if (addrConnect.GetNetwork() == NET_I2P && m_i2p_sam_session.get() != nullptr) {
     435 | +            i2p::Connection conn;
     436 | +            if (m_i2p_sam_session->Connect(addrConnect, conn, proxyConnectionFailed)) {
     437 | +                connected = true;
     438 | +                *sock = std::move(conn.sock);
    


    jonatack commented at 3:59 PM on February 14, 2021:

    Both gdb and valgrind are hitting this line


    vasild commented at 9:32 AM on February 15, 2021:

    Yes, that is an invalid way to assign a new value to unique_ptr that is not set. :bomb: Fixed!


    jonatack commented at 9:37 AM on February 15, 2021:

    Makes sense. Building the new push.

  102. laanwj commented at 7:24 PM on February 14, 2021: member

    So it hits an illegal instruction on this line:

       0x0000555555621ede <+2638>:	mov    (%rax),%rcx
    

    This is really strange. That looks like a perfectly basic x86 instruction. I could understand a segmentation fault here, but illegal instruction is strange. At least it is in code that is affected by this PR.

  103. jonatack commented at 9:01 AM on February 15, 2021: member

    The previous tests were with clang 9; seeing the same segfault with gcc 10.2.1:

    $ gcc --version
    gcc (Debian 10.2.1-6) 10.2.1 20210110
    $ gdb bitcoind
    GNU gdb (Debian 10.1-1.7) 10.1.90.20210103-git
    
    2021-02-15T08:47:39Z I2P: SAM session created: session id=qqqq, my address=qqqq.b32.i2p:8333
    2021-02-15T08:47:39Z AddLocal(qqqq.b32.i2p:8333,2)
    2021-02-15T08:47:47Z UpdateTip: new best=000000000000000000099c233db18ba6797892a9d0e0a915207ceb635b39f21c height=670691 version=0x20600000 log2_work=92.669960 tx=616400432 date='2021-02-15T08:47:12Z' progress=1.000000 cache=9.3MiB(70444txo)
    2021-02-15T08:47:48Z New outbound peer connected: version: 70015, blocks=670691, peer=9, peeraddr=jvmq5xt2xcbe32ug.onion:8333 (outbound-full-relay)
    
    Thread 18 "b-addcon" received signal SIGSEGV, Segmentation fault.
    [Switching to Thread 0x7fff4baf1700 (LWP 55615)]
    CConnman::ConnectNode (this=0x555556c59f50, addrConnect=..., pszDest=0x7fff28002e50 "qqqq.b32.i2p", 
        fCountFailure=false, conn_type=ConnectionType::MANUAL) at net.cpp:437
    437	                *sock = std::move(conn.sock);
    
    (gdb) disass /m
    .../...
    437	                *sock = std::move(conn.sock);
       0x00005555555fb83a <+1692>:	lea    -0x3e8(%rbp),%rax
       0x00005555555fb841 <+1699>:	mov    %rax,%rdi
       0x00005555555fb844 <+1702>:	call   0x55555561c796 <_ZNKSt10unique_ptrI4SockSt14default_deleteIS0_EEdeEv>
       0x00005555555fb849 <+1707>:	mov    %rax,%rbx
    => 0x00005555555fb84c <+1710>:	mov    (%rbx),%rax
       0x00005555555fb84f <+1713>:	add    $0x10,%rax
       0x00005555555fb853 <+1717>:	mov    (%rax),%r12
       0x00005555555fb856 <+1720>:	lea    -0x90(%rbp),%rax
       0x00005555555fb85d <+1727>:	mov    %rax,%rdi
       0x00005555555fb860 <+1730>:	call   0x55555561c7d7 <_ZSt4moveIR4SockEONSt16remove_referenceIT_E4typeEOS3_>
       0x00005555555fb865 <+1735>:	mov    %rax,%rsi
       0x00005555555fb868 <+1738>:	mov    %rbx,%rdi
       0x00005555555fb86b <+1741>:	call   *%r12
    

    <details><summary>backtrace</summary><p>

    (gdb) bt
    [#0](/bitcoin-bitcoin/0/)  CConnman::ConnectNode (this=0x555556c59f50, addrConnect=..., pszDest=0x7fff28002e50 "qqqq.b32.i2p", 
        fCountFailure=false, conn_type=ConnectionType::MANUAL) at net.cpp:437
    [#1](/bitcoin-bitcoin/1/)  0x0000555555605be1 in CConnman::OpenNetworkConnection (this=0x555556c59f50, addrConnect=..., fCountFailure=false, grantOutbound=0x7fff4baf0810, 
        pszDest=0x7fff28002e50 "qqqq.b32.i2p", conn_type=ConnectionType::MANUAL) at net.cpp:2152
    [#2](/bitcoin-bitcoin/2/)  0x000055555560581c in CConnman::ThreadOpenAddedConnections (this=0x555556c59f50) at net.cpp:2119
    [#3](/bitcoin-bitcoin/3/)  0x00005555556605f2 in std::__invoke_impl<void, void (CConnman::*&)(), CConnman*&> (
        __f=@0x5555639f9670: (void (CConnman::*)(CConnman * const)) 0x555555605692 <CConnman::ThreadOpenAddedConnections()>, __t=@0x5555639f9680: 0x555556c59f50)
        at /usr/include/c++/10/bits/invoke.h:73
    [#4](/bitcoin-bitcoin/4/)  0x000055555565e4bf in std::__invoke<void (CConnman::*&)(), CConnman*&> (
        __fn=@0x5555639f9670: (void (CConnman::*)(CConnman * const)) 0x555555605692 <CConnman::ThreadOpenAddedConnections()>) at /usr/include/c++/10/bits/invoke.h:95
    [#5](/bitcoin-bitcoin/5/)  0x000055555565b1b7 in std::_Bind<void (CConnman::*(CConnman*))()>::__call<void, , 0ul>(std::tuple<>&&, std::_Index_tuple<0ul>) (this=0x5555639f9670, 
        __args=...) at /usr/include/c++/10/functional:416
    [#6](/bitcoin-bitcoin/6/)  0x00005555556559df in std::_Bind<void (CConnman::*(CConnman*))()>::operator()<, void>() (this=0x5555639f9670) at /usr/include/c++/10/functional:499
    [#7](/bitcoin-bitcoin/7/)  0x000055555564dddb in std::__invoke_impl<void, std::_Bind<void (CConnman::*(CConnman*))()>&>(std::__invoke_other, std::_Bind<void (CConnman::*(CConnman*))()>&)
        (__f=...) at /usr/include/c++/10/bits/invoke.h:60
    [#8](/bitcoin-bitcoin/8/)  0x00005555556423ae in std::__invoke_r<void, std::_Bind<void (CConnman::*(CConnman*))()>&>(std::_Bind<void (CConnman::*(CConnman*))()>&) (__fn=...)
        at /usr/include/c++/10/bits/invoke.h:110
    [#9](/bitcoin-bitcoin/9/)  0x00005555556327d0 in std::_Function_handler<void (), std::_Bind<void (CConnman::*(CConnman*))()> >::_M_invoke(std::_Any_data const&) (__functor=...)
        at /usr/include/c++/10/bits/std_function.h:291
    [#10](/bitcoin-bitcoin/10/) 0x00005555555cda5f in std::function<void ()>::operator()() const (this=0x7fff4baf0b20) at /usr/include/c++/10/bits/std_function.h:622
    [#11](/bitcoin-bitcoin/11/) 0x00005555555c2aa5 in TraceThread<std::function<void ()> >(char const*, std::function<void ()>) (name=0x555556000af8 "addcon", func=...) at ./util/system.h:470
    [#12](/bitcoin-bitcoin/12/) 0x0000555555662ea0 in std::__invoke_impl<void, void (*)(char const*, std::function<void ()>), char const*, std::function<void ()> >(std::__invoke_other, void (*&&)(char const*, std::function<void ()>), char const*&&, std::function<void ()>&&) (
        __f=@0x55555ff62670: 0x5555555c2a1b <TraceThread<std::function<void ()> >(char const*, std::function<void ()>)>) at /usr/include/c++/10/bits/invoke.h:60
    [#13](/bitcoin-bitcoin/13/) 0x0000555555662d16 in std::__invoke<void (*)(char const*, std::function<void ()>), char const*, std::function<void ()> >(void (*&&)(char const*, std::function<void ()>), char const*&&, std::function<void ()>&&) (
        __fn=@0x55555ff62670: 0x5555555c2a1b <TraceThread<std::function<void ()> >(char const*, std::function<void ()>)>) at /usr/include/c++/10/bits/invoke.h:95
    [#14](/bitcoin-bitcoin/14/) 0x0000555555662b82 in std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, std::function<void ()> > >::_M_invoke<0ul, 1ul, 2ul>(std::_Index_tuple<0ul, 1ul, 2ul>) (this=0x55555ff62648) at /usr/include/c++/10/thread:264
    [#15](/bitcoin-bitcoin/15/) 0x0000555555662af9 in std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, std::function<void ()> > >::operator()() (
        this=0x55555ff62648) at /usr/include/c++/10/thread:271
    [#16](/bitcoin-bitcoin/16/) 0x0000555555662ab7 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, std::function<void ()> > > >::_M_run() (this=0x55555ff62640) at /usr/include/c++/10/thread:215
    [#17](/bitcoin-bitcoin/17/) 0x00007ffff7beced0 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
    [#18](/bitcoin-bitcoin/18/) 0x00007ffff7f8aea7 in start_thread (arg=<optimized out>) at pthread_create.c:477
    [#19](/bitcoin-bitcoin/19/) 0x00007ffff78f8def in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
    (gdb) 
    

    </p></details>

  104. vasild force-pushed on Feb 15, 2021
  105. vasild commented at 9:30 AM on February 15, 2021: member

    a456bd3f2..da2ba3e87: don't dereference an unset unique_ptr, thanks @jonatack, @laanwj!

  106. jonatack commented at 10:14 AM on February 15, 2021: member

    Thanks -- da2ba3e following the fix is working now.

  107. DrahtBot added the label Needs rebase on Feb 15, 2021
  108. vasild force-pushed on Feb 15, 2021
  109. vasild commented at 3:47 PM on February 15, 2021: member

    da2ba3e87...e19bc9938: rebase due to conflicts

  110. in src/netbase.cpp:81 in 433d9a9f1e outdated
      77 | @@ -78,7 +78,7 @@ std::vector<std::string> GetNetworkNames(bool append_unroutable)
      78 |      std::vector<std::string> names;
      79 |      for (int n = 0; n < NET_MAX; ++n) {
      80 |          const enum Network network{static_cast<Network>(n)};
      81 | -        if (network == NET_UNROUTABLE || network == NET_I2P || network == NET_CJDNS || network == NET_INTERNAL) continue;
      82 | +        if (network == NET_UNROUTABLE || network == NET_CJDNS || network == NET_INTERNAL) continue;
    


    jonatack commented at 4:17 PM on February 15, 2021:

    This will need the following change (if not already made but I didn't see it)

    /test/functional/rpc_net.py
    @@ -105,7 +105,7 @@ class NetTest(BitcoinTestFramework):
             assert_equal(peer_info[1][1]['connection_type'], 'inbound')
     
             # Check dynamically generated networks list in getpeerinfo help output.
    -        assert "(ipv4, ipv6, onion, not_publicly_routable)" in self.nodes[0].help("getpeerinfo")
    +        assert "(ipv4, ipv6, onion, i2p, not_publicly_routable)" in self.nodes[0].help("getpeerinfo")
     
         def test_getnettotals(self):
             self.log.info("Test getnettotals")
    @@ -156,7 +156,7 @@ class NetTest(BitcoinTestFramework):
                 assert_net_servicesnames(int(info["localservices"], 0x10), info["localservicesnames"])
     
             # Check dynamically generated networks list in getnetworkinfo help output.
    -        assert "(ipv4, ipv6, onion)" in self.nodes[0].help("getnetworkinfo")
    +        assert "(ipv4, ipv6, onion, i2p)" in self.nodes[0].help("getnetworkinfo")
     
         def test_getaddednodeinfo(self):
    

    vasild commented at 3:18 PM on February 16, 2021:

    Fixed, thanks!

  111. DrahtBot removed the label Needs rebase on Feb 15, 2021
  112. vasild force-pushed on Feb 16, 2021
  113. vasild commented at 3:18 PM on February 16, 2021: member

    433d9a9f1...2a7bb343a: fix failing rpc_net.py

  114. laanwj commented at 8:02 AM on February 17, 2021: member

    I'm trying with i2pd now on FreeBSD. Not having much luck. I could install it and start it quite easily (much more easily than the Java one):

    $ pkg install i2pd
    # add i2pd_enable="YES"  and optionally i2pd_flags="--bandwidth X"
    $ vi /etc/rc.conf
    $ service i2pd start
    $ i2pd --version
    i2pd version 2.33.0 (0.9.47)
    

    That's it. SAM is enabled on port 7656.

    Edit: below issue is fixed


    However, it doesn't seem to succesfully start the I2P listener. It looks like it hangs after sending the session create, doesn't get a reply.

    2021-02-17T07:52:35Z I2P: Creating SAM session with 127.0.0.1:7656
    ⋮
    2021-02-17T07:55:35Z I2P: Error listening: Receive timeout (received 0 bytes without terminator before that)
    2021-02-17T07:55:35Z I2P: Control socket error: not connected
    

    On the i2pd side:

    08:55:36@682/error - NetDb: runtime exception: No known routers, reseed seems to be totally failed
    08:55:36@270/debug - SAM: new connection from 127.0.0.1:14315
    08:55:36@270/debug - SAM: handshake HELLO VERSION MIN=3.1 MAX=3.1
    08:55:36@270/debug - SAM: session create: STYLE=STREAM ID=b66590c3b4 DESTINATION=[snip]
    08:55:36@270/warn - Clients: Local destination [snip].b32.i2p exists
    08:55:37@7/warn - Tunnel: can't find any router, skip creating tunnel
    08:55:37@7/debug - Tunnels: Creating destination outbound tunnel...
    ⋮
    09:00:07@7/error - Tunnels: Can't create inbound tunnel, no peers available
    09:00:07@7/debug - Tunnels: Creating destination inbound tunnel...
    09:00:07@7/error - Tunnels: Can't select next hop for G[snip]=
    09:00:07@7/error - Tunnels: Can't create inbound tunnel, no peers available
    

    The latter part keeps repeating and repeating. It looks like a problem on the i2pd side not the bitcoind one. I have no networking issues, IPv4 and IPv6 and Tor works on the host. Anyone with ideas?

  115. jonatack commented at 9:03 AM on February 17, 2021: member

    If this is the issue Suhas encountered, upgrade to i2pd v2.35 (latest release, build from source or on Debian it's in the testing sources).

  116. laanwj commented at 9:07 AM on February 17, 2021: member

    I don't think it's the same issue. He had a much older version (2.23 instead of 2.33), which had problems handling the commands from bitcoind. My i2pd seems completely broken, it doesn't get any peer connections.

    The whole "runtime exception: No known routers, reseed seems to be totally failed" message gives only one result on Google, some Russian github thread. Argh.

    Edit: oh, it could have been something with clock skew. After running ntpdate europe.pool.ntp.org and restarting the service it seems to be doing more!

    10:14:29@122/error - SSU: clock skew detected 4294967197. Check your clock
    

    Edit.2 yes, that fixed it!:

    2021-02-17T09:21:44Z I2P: SAM session created: session id=be83961cec, my address=[snip].b32.i2p:8333
    2021-02-17T09:21:44Z AddLocal([snip].b32.i2p:8333,2)
    
  117. laanwj commented at 8:45 AM on February 22, 2021: member

    Code review and extensively manually tested ACK 2a7bb343ac77f2bf52ea1a8959a22ef266d49aa6

    I think it would be nice to have unit tests for the Reply parsing in i2p.cpp and maybe the alt-Base64 parsing, however this can be done in a later PR (and doesn't need to hold up progress here). Maybe someone will even look into fuzzing.

  118. jonatack commented at 11:02 AM on February 25, 2021: member

    Update, about halfway through reviewing the commits. Each builds cleanly and no comments so far.

    I've been testing this these past weeks using i2pd 2.35. Apparently, i2pd 2.36 was released last week and I plan to test with it.

    The only oddity I've been seeing from the first day of testing until now is inbound I2P peers can regularly have two connections, present for a few minutes. I haven't looked further into it yet. Here are two screenshots taken on February 14 and 20:

    Screenshot from 2021-02-14 01-33-45

    Screenshot from 2021-02-20 11-37-26

  119. ghost commented at 8:15 PM on February 25, 2021: none
    1. Unable to build for Windows using instructions mentioned in this doc: https://github.com/bitcoin/bitcoin/blob/master/doc/build-windows.md (It worked for other pull request recently)

    <pre> CXXLD bitcoind.exe CXXLD bitcoin-wallet.exe CXXLD test/test_bitcoin.exe CXXLD bench/bench_bitcoin.exe CXXLD test/fuzz/fuzz.exe AR qt/libbitcoinqt.a /usr/bin/x86_64-w64-mingw32-ld: /usr/lib/gcc/x86_64-w64-mingw32/9.3-posix/../../../../x86_64-w64-mingw32/lib/libmingw32.a(lib64_libmingw32_a-crt0_c.o): in function `main': ./build/x86_64-w64-mingw32-x86_64-w64-mingw32-crt/./mingw-w64-crt/crt/crt0_c.c:18: undefined reference to `WinMain' collect2: error: ld returned 1 exit status make[2]: *** [Makefile:5863: test/fuzz/fuzz.exe] Error 1 make[2]: *** Waiting for unfinished jobs.... make[2]: Leaving directory '/home/rebel/bitcoin/src' make[1]: *** [Makefile:15177: all-recursive] Error 1 make[1]: Leaving directory '/home/rebel/bitcoin/src' make: *** [Makefile:809: all-recursive] Error 1 </pre>

    1. Compiled successfully on Ubuntu 20.04.2 LTS. Tests passed.

    Installed i2p with the instructions mentioned here: https://geti2p.net/en/download/debian followed by i2prouter start

    bitcoin.conf file:

    <pre> testnet=1 prune=555 i2psam=127.0.0.1:7658 i2pacceptincoming=1 </pre>

    Don't see any i2p_private_key file created in .bitcoin/testnet3

    Logs:

    <pre> 2021-02-25T20:12:16Z i2paccept thread start 2021-02-25T20:12:16Z msghand thread start 2021-02-25T20:12:16Z opencon thread start 2021-02-25T20:12:16Z dnsseed thread start 2021-02-25T20:12:16Z Waiting 300 seconds before querying DNS seeds. 2021-02-25T20:12:16Z addcon thread start 2021-02-25T20:12:16Z GUI: Platform customization: "other" 2021-02-25T20:12:16Z tor: Got service ID omy7kj7zwvfg5luayideh73uqb2latkoyyy5h65y4atv3fymnlxlzwqd, advertising service omy7kj7zwvfg5luayideh73uqb2latkoyyy5h65y4atv3fymnlxlzwqd.onion:18333 2021-02-25T20:12:16Z AddLocal(omy7kj7zwvfg5luayideh73uqb2latkoyyy5h65y4atv3fymnlxlzwqd.onion:18333,4) 2021-02-25T20:12:17Z New outbound peer connected: version: 70015, blocks=1937809, peer=0 (block-relay-only) 2021-02-25T20:12:18Z New outbound peer connected: version: 70015, blocks=1937809, peer=1 (block-relay-only) 2021-02-25T20:12:18Z Synchronizing blockheaders, height: 1937809 (~100.00%) </pre>

  120. laanwj commented at 8:26 PM on February 25, 2021: member

    @prayank23 Strange. Adding debug=i2p to your config might give some more information in the log as to why it's not working.

    The windows linker issue seems unrelated (you could create a new issue for it if you want).

  121. ghost commented at 9:29 PM on February 25, 2021: none

    <pre> 2021-02-25T21:25:14Z i2paccept thread start 2021-02-25T21:25:14Z I2P: Creating SAM session with 127.0.0.1:7658 2021-02-25T21:25:14Z net thread start 2021-02-25T21:25:14Z GUI: Platform customization: "other" 2021-02-25T21:25:15Z I2P: Error listening: Missing RESULT= in the reply to 'HELLO VERSION MIN=3.1 MAX=3.1': 'HTTP/1.1 400 Illegal character SPACE=' '\x0d' 2021-02-25T21:25:15Z I2P: Control socket error: not connected </pre>

  122. laanwj commented at 9:39 PM on February 25, 2021: member

    It doesn't look like it's a SAM proxy you're connecting to, but a HTTP proxy (it's clearly speaking HTTP). From what I remember the Java I2P router doesn't start a SAM service by default and you need to add it.

  123. fanquake commented at 2:00 AM on February 26, 2021: member

    Unable to build for Windows

    The Windows linking issue has been fixed in master in #21226. This PR just needs rebasing.

  124. vasild commented at 4:32 PM on February 26, 2021: member

    @jonatack, next time you observe two incoming connections from the same peer, try to capture the output of bitcoin-cli getpeerinfo |jq 'map(select(.network == "i2p")) |map({inbound: .inbound, addr: .addr, addrbind: .addrbind})'. I suspect it has something to do with the ports. @prayank23, the SAM proxy is usually listening on port 7656. Surely it can be changed to anything, but I guess you did not change it and your config i2psam=127.0.0.1:7658 is pointing to the HTTP proxy, as @laanwj mentioned.

  125. jonatack commented at 5:06 PM on February 26, 2021: member

    @prayank23 yes, fwiw I'm building and reviewing the PR after rebasing to current master (let it run last night building and testing each commit and they are all clean/green), as mentioned above, if you do that it should(:tm:) build on Windows. @vasild sure np. Should finish reviewing the current branch today.

  126. in src/netaddress.h:156 in 2a7bb343ac outdated
     150 | @@ -151,7 +151,16 @@ class CNetAddr
     151 |  
     152 |          bool SetInternal(const std::string& name);
     153 |  
     154 | -        bool SetSpecial(const std::string &strName); // for Tor addresses
     155 | +        /**
     156 | +         * Parse a Tor or I2P address and set this object to it.
     157 | +         * @param[in] name Address to parse, for example
    


    jonatack commented at 5:56 PM on February 26, 2021:

    2ee63a5 For the six SetSpecial, SetTor and SetI2P declarations and definitions, I think it would be clearer to use the same param name. It's currently sometimes name and sometimes str and different between the declarations and the definitions for SetTor and SetI2P. (I'd propose const std::string& addr for all six.)


    vasild commented at 5:08 PM on March 1, 2021:

    Done.

  127. in src/util/sock.cpp:171 in 2a7bb343ac outdated
     167 | +                "Send interrupted (sent only %u of %u bytes before that)", sent, data.size()));
     168 | +        }
     169 | +
     170 | +        // Wait for a short while (or the socket to become ready for sending) before retrying
     171 | +        // if nothing was sent.
     172 | +        const auto timeout = std::min(deadline - now, std::chrono::milliseconds{MAX_WAIT_FOR_IO});
    


    jonatack commented at 7:57 PM on February 26, 2021:

    45cfaf0d296b6b6f9d4c86d4ec1b4c4392947b36 here and also line 248, maybe use a different name for the timeout local variable (maybe wait_time or wait_timeout) than the timeout input param


    vasild commented at 5:08 PM on March 1, 2021:

    Done.

  128. in src/util/sock.cpp:187 in 2a7bb343ac outdated
     183 | +    bool terminator_found = false;
     184 | +
     185 | +    // We must not consume any bytes past the terminator from the socket.
     186 | +    // One option is to read one byte at a time and check if we have read a terminator.
     187 | +    // However that is very slow. Instead, we peek at what is in the socket and only read
     188 | +    // as much bytes as possible without crossing the terminator.
    


    jonatack commented at 7:59 PM on February 26, 2021:

    45cfaf0

        // as many bytes as possible without crossing the terminator.
    

    vasild commented at 5:09 PM on March 1, 2021:

    Done.

  129. in src/util/sock.cpp:225 in 2a7bb343ac outdated
     221 | +                              "peek claimed %u bytes are available",
     222 | +                              read_ret, try_len, peek_ret));
     223 | +            }
     224 | +
     225 | +            // Don't include the terminator in the output.
     226 | +            const size_t append_len = terminator_found ? read_ret - 1 : read_ret;
    


    jonatack commented at 8:17 PM on February 26, 2021:

    45cfaf0d296b6b6f9d4c86d4ec1b4c4392947b36 maybe make explicit that this is narrowing from long to unsigned long (size_t)

                const size_t append_len{static_cast<size_t>(terminator_found ? read_ret - 1 : read_ret)};
    

    (In general, in these two added functions Sock::SendComplete() and Sock::RecvUntilTerminator(), I would personally find it more clear and reassuring if uniform initialization with explicit typing was used.)


    vasild commented at 5:10 PM on March 1, 2021:

    In this case we can use try_len which is size_t and we already checked that it equals to read_ret just above this snippet.

  130. in src/i2p.h:198 in 2a7bb343ac outdated
     193 | +     * @throws std::runtime_error if an error occurs
     194 | +     */
     195 | +    void CreateIfNotCreatedAlready() EXCLUSIVE_LOCKS_REQUIRED(m_mutex);
     196 | +
     197 | +    /**
     198 | +     * Open a new connection to the SAM proxy and issue "STREAM ACCEPT" request using the existent
    


    jonatack commented at 9:05 PM on February 26, 2021:

    6da5c7eb32b51ab89f27a84e6c5e33db0e8e3e6e

         * Open a new connection to the SAM proxy and issue "STREAM ACCEPT" request using the existing
    

    vasild commented at 5:10 PM on March 1, 2021:

    Done.

  131. in src/i2p.h:246 in 2a7bb343ac outdated
     241 | +     * See https://geti2p.net/en/docs/api/samv3
     242 | +     */
     243 | +    Sock m_control_sock GUARDED_BY(m_mutex);
     244 | +
     245 | +    /**
     246 | +     * The .b32.i2p address of this peer.
    


    jonatack commented at 9:10 PM on February 26, 2021:

    6da5c7e A peer = a node that is not us. If m_my_addr is for our own address only, maybe s/this peer/our node/ or * Our .b32.i2p address.


    vasild commented at 5:11 PM on March 1, 2021:

    Done.

  132. in src/init.cpp:451 in 2a7bb343ac outdated
     445 | @@ -446,7 +446,9 @@ void SetupServerArgs(NodeContext& node)
     446 |      argsman.AddArg("-maxtimeadjustment", strprintf("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)", DEFAULT_MAX_TIME_ADJUSTMENT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
     447 |      argsman.AddArg("-maxuploadtarget=<n>", strprintf("Tries to keep outbound traffic under the given target (in MiB per 24h). Limit does not apply to peers with 'download' permission. 0 = no limit (default: %d)", DEFAULT_MAX_UPLOAD_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
     448 |      argsman.AddArg("-onion=<ip:port>", "Use separate SOCKS5 proxy to reach peers via Tor onion services, set -noonion to disable (default: -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
     449 | -    argsman.AddArg("-onlynet=<net>", "Make outgoing connections only through network <net> (" + Join(GetNetworkNames(), ", ") + "). Incoming connections are not affected by this option. This option can be specified multiple times to allow multiple networks. Warning: if it is used with ipv4 or ipv6 but not onion and the -onion or -proxy option is set, then outbound onion connections will still be made; use -noonion or -onion=0 to disable outbound onion connections in this case.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
     450 | +    argsman.AddArg("-i2psam=<ip:port>", "I2P SAM proxy to reach I2P peers and accept I2P connections (default: none)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
     451 | +    argsman.AddArg("-i2pacceptincoming", "If set and -i2psam is also set then incoming I2P connections are accepted via the SAM proxy. If this is not set but -i2psam is set then only outgoing connections will be made to the I2P network. Ignored if -i2psam is not set. Notice that listening for incoming I2P connections is done through the SAM proxy, not by binding to a local address and port (default: 1)", ArgsManager::ALLOW_BOOL, OptionsCategory::CONNECTION);
    


    jonatack commented at 10:19 PM on February 26, 2021:

    300a654feb8cc68fc12bc8baff0f69ef031bd51f s/Notice/Note/ (or just omit "Notice that")

        argsman.AddArg("-i2pacceptincoming", "If set and -i2psam is also set then incoming I2P connections are accepted via the SAM proxy. If this is not set but -i2psam is set then only outgoing connections will be made to the I2P network. Ignored if -i2psam is not set. Listening for incoming I2P connections is done through the SAM proxy, not by binding to a local address and port (default: 1)", ArgsManager::ALLOW_BOOL, OptionsCategory::CONNECTION);
    

    vasild commented at 5:10 PM on March 1, 2021:

    Done.

  133. in src/init.cpp:2000 in 2a7bb343ac outdated
    1990 | @@ -1986,6 +1991,21 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
    1991 |              connOptions.m_specified_outgoing = connect;
    1992 |          }
    1993 |      }
    1994 | +
    1995 | +    const std::string& i2psam_arg = args.GetArg("-i2psam", "");
    1996 | +    if (i2psam_arg != "") {
    


    jonatack commented at 10:21 PM on February 26, 2021:

    300a654feb8cc68fc12bc8baff0f69ef031bd51f

        if (!i2psam_arg.empty()) {
    

    vasild commented at 5:11 PM on March 1, 2021:

    Done.

  134. in src/i2p.cpp:365 in 2a7bb343ac outdated
     359 | +    const std::string& private_key_b64 = SwapBase64(EncodeBase64(m_private_key));
     360 | +
     361 | +    SendRequestAndGetReply(sock, strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s",
     362 | +                                           session_id, private_key_b64));
     363 | +
     364 | +    m_my_addr = CService(DestBinToAddr(MyDestination()), Params().GetDefaultPort());
    


    jonatack commented at 7:16 PM on February 27, 2021:
        m_my_addr = CService{DestBinToAddr(MyDestination()), static_cast<uint16_t>(Params().GetDefaultPort())};
    

    luke-jr commented at 10:13 PM on February 28, 2021:

    Why?


    jonatack commented at 10:31 PM on February 28, 2021:

    To be explicit about the narrowing conversion, same as #20685 (review) above


    luke-jr commented at 10:36 PM on February 28, 2021:

    Being explicit with a static_cast has no benefits I'm aware of, just would silence warnings in cases where the warning is warranted...?


    jonatack commented at 11:18 AM on March 1, 2021:

    @luke-jr I think it's the opposite, brace (uniform) initialization raises compile time warnings, e.g. for narrowing and conversions, and named casts provide compile time checks as well.

    "Use brace initialization to convert arithmetic types (e.g., int64{x}). This is the safest approach because code will not compile if conversion can result in information loss. The syntax is also concise. Use static_cast as the equivalent of a C-style cast that does value conversion."

    "Brace initialization makes it clear that the type conversion was intended and also prevents conversions between types that might result in loss of precision. (It is a compilation error to try to initialize a float from a double in this fashion, for example.)"


    jonatack commented at 11:21 AM on March 1, 2021:

    For example, without the named cast here, brace initialization raises a compile time error for the narrowing conversion.


    vasild commented at 4:42 PM on March 1, 2021:

    The thing is that here GetDefaultPort() returns int and CService constructor takes uint16_t argument. So we would get a justified warning that we want to silence. The proper fix would be to change GetDefaultPort() to return uint16_t which is out of the scope of this PR.

    I don't see a point in using a brace initialization for the warning and then to silence the warning with a static_cast.

    int x = 300;
    
    // no warning
    uint16_t c1 = x;
    
    // non-constant-expression cannot be narrowed from type 'int' to 'uint16_t'
    uint16_t c2{x};
    
    // no warning
    uint16_t c3{static_cast<uint16_t>(x)};
    

    Left it as is.


    jonatack commented at 4:50 PM on March 1, 2021:

    I agree it can be considered out of scope to change GetDefaultPort(), but the suggested (ugly!) change would make explicit the type mismatch and maybe encourage improving it. As mentioned in the parent comment, none of these are blockers, just items I noted while reviewing.


    jonatack commented at 4:59 PM on March 1, 2021:

    Anyway, no worries. I'll look into improving it.


    jonatack commented at 10:26 PM on March 1, 2021:

    Proposed #21328 to address it without requiring any changes here.

  135. jonatack commented at 7:48 PM on February 27, 2021: member

    ACK 2a7bb343ac77f2bf52ea1a8959a22ef266d49aa6 modulo a few comments below and more suggestions in the top commit at https://github.com/jonatack/bitcoin/commits/pr20685-review. In addition, it looks like src/i2p.{h,cpp} could benefit from unit test coverage. After rebasing to current master at b54a10e777f91208, I checked that each of the commits is hygienic, e.g. debug-builds cleanly with clang 9 and unit tests pass. I have also been running a node on this branch on and off since a few months with i2pd 2.35.0, and apart from the same peer being able to make more than one inbound connection, it appears to be running well and the 2 outbound and 1 inbound I2P peer connections I've been seeing appear to be at least as robust as the other ones, though generally with higher ping times (which I believe is inherent to the I2P network and not related to this change).

    None of my suggestions below or in the linked branch are blockers but I'm happy to re-review very responsively if you update. That said, this seems to be working robustly and I think it would be good to merge this soon and not too late in this release cycle, with test coverage added in a follow-up.

  136. practicalswift commented at 7:53 PM on February 28, 2021: contributor

    @laanwj

    I think it would be nice to have unit tests for the Reply parsing in i2p.cpp and maybe the alt-Base64 parsing, however this can be done in a later PR (and doesn't need to hold up progress here). Maybe someone will even look into fuzzing.

    Agreed! I plan to add a fuzzing harness for the I2P Reply parsing code (unless @vasild plans to do it as part of this PR of course :)).

    Shameless plug: a fuzzing harness for the Tor controller reply parsing code was submitted in June last year in the still open PR #19288. Review welcome! :)

  137. ghost commented at 10:14 PM on February 28, 2021: none

    Finally i2p_private_key created :)

    image

    It was port: 7656 and I had to use i2pd instead of i2prouter. Thanks for the help @laanwj @vasild @jonatack @fanquake Thanks. Will try to build for Windows. I think we will also need a i2p.md file in docs for everyone to setup i2p service for Bitcoin Core.

  138. jonatack commented at 10:27 PM on February 28, 2021: member

    I think we will also need a i2p.md file in docs for everyone to setup i2p service for Bitcoin Core. @prayank23 yes, discussed above at #20685 (comment)

  139. laanwj commented at 10:59 AM on March 1, 2021: member

    I would recommend against extending the scope of this PR. Let's make sure that this change is correct, address remaining comments, and then merge it. It's useful to have this on the branch so that other people can work on it. Documentation and additional testing can be added in a later PR.

  140. jonatack commented at 11:27 AM on March 1, 2021: member

    It's useful to have this on the branch so that other people can work on it.

    Agree! Though per @vasild's IRC comments last week (http://www.erisian.com.au/bitcoin-core-dev/log-2021-02-25.html#l-242) he may have planned one more update.

  141. util: extract {Read,Write}BinaryFile() to its own files
    Extract `ReadBinaryFile()` and `WriteBinaryFile()` from `torcontrol.cpp`
    to its own `readwritefile.{h,cpp}` files, so that it can be reused from
    other modules.
    4cba2fdafa
  142. util: fix ReadBinaryFile() returning partial contents
    If an error occurs and `fread()` returns `0` (nothing was read) then the
    code before this patch would have returned "success" with a partially
    read contents of the file.
    8b6e4b3b23
  143. util: fix WriteBinaryFile() claiming success even if error occurred
    `fclose()` is flushing any buffered data to disk, so if it fails then
    that could mean that the data was not completely written to disk.
    
    Thus, check if `fclose()` succeeds and only then claim success from
    `WriteBinaryFile()`.
    545bc5f81d
  144. net: check for invalid socket earlier in CConnman::AcceptConnection()
    This check is related to an `accept()` failure. So do the check earlier,
    closer to the `accept()` call.
    
    This will allow to isolate the `accept()`-specific code at the beginning
    of `CConnman::AcceptConnection()` and reuse the code that follows it.
    25605895af
  145. net: get the bind address earlier in CConnman::AcceptConnection()
    Call `GetBindAddress()` earlier in `CConnman::AcceptConnection()`. That
    is specific to the TCP protocol and makes the code below it reusable for
    other protocols, if the caller provides `addr_bind`, retrieved by other
    means.
    1f75a653dd
  146. net: isolate the protocol-agnostic part of CConnman::AcceptConnection()
    Isolate the second half of `CConnman::AcceptConnection()` into a new
    separate method, which could be reused if we accept incoming connections
    by other means than `accept()` (first half of
    `CConnman::AcceptConnection()`).
    7c224fdac4
  147. net: avoid unnecessary GetBindAddress() call
    Our local (bind) address is already saved in `CNode::addrBind` and there
    is no need to re-retrieve it again with `GetBindAddress()`.
    
    Also, for I2P connections `CNode::addrBind` would contain our I2P
    address, but `GetBindAddress()` would return something like
    `127.0.0.1:RANDOM_PORT`.
    f6c267db3b
  148. vasild force-pushed on Mar 1, 2021
  149. vasild commented at 12:14 PM on March 1, 2021: member

    2a7bb343a...e41cb7dbd: rebase to fix the windows fuzz build issue

  150. net: extend CNetAddr::SetSpecial() to support I2P
    Recognize also I2P addresses in the form `base32hashofpublickey.b32.i2p`
    from `CNetAddr::SetSpecial()`.
    
    This makes `Lookup()` support them, which in turn makes it possible to
    manually connect to an I2P node by using
    `-proxy=i2p_socks5_proxy:port -addnode=i2p_address.b32.i2p:port`
    
    Co-authored-by: Lucas Ontivero <lucasontivero@gmail.com>
    cff65c4a27
  151. net: move the constant maxWait out of InterruptibleRecv()
    Move `maxWait` out of `InterruptibleRecv()` and rename it to
    `MAX_WAIT_FOR_IO` so that it can be reused by other code.
    34bcfab562
  152. net: dedup MSG_NOSIGNAL and MSG_DONTWAIT definitions
    Deduplicate `MSG_NOSIGNAL` and `MSG_DONTWAIT` definitions from `net.cpp`
    and `netbase.cpp` to `compat.h` where they can also be reused by other
    code.
    78fdfbea66
  153. net: extend Sock::Wait() to report a timeout
    Previously `Sock::Wait()` would not have signaled to the caller whether
    a timeout or one of the requested events occurred since that was not
    needed by any of the callers.
    
    Such functionality will be needed in the I2P implementation, thus extend
    the `Sock::Wait()` method.
    ea1845315a
  154. net: extend Sock with methods for robust send & read until terminator
    Introduce two high level, convenience methods in the `Sock` class:
    
    * `SendComplete()`: keep trying to send the specified data until either
      successfully sent all of it, timeout or interrupted.
    
    * `RecvUntilTerminator()`: read until a terminator is encountered (never
      after it), timeout or interrupted.
    
    These will be convenient in the I2P SAM implementation.
    
    `SendComplete()` can also be used in the SOCKS5 implementation instead
    of calling `send()` directly.
    42c779f503
  155. net: extend Sock with a method to check whether connected
    This will be convenient in the I2P SAM implementation.
    5bac7e45e1
  156. vasild force-pushed on Mar 1, 2021
  157. vasild commented at 5:08 PM on March 1, 2021: member

    e41cb7dbd...f181f24ca: address suggestions (no tests yet)

  158. net: implement the necessary parts of the I2P SAM protocol
    Implement the following commands from the I2P SAM protocol:
    
    * HELLO: needed for all of the remaining ones
    * DEST GENERATE: to generate our private key and destination
    * NAMING LOOKUP: to convert .i2p addresses to destinations
    * SESSION CREATE: needed for STREAM CONNECT and STREAM ACCEPT
    * STREAM CONNECT: to make outgoing connections
    * STREAM ACCEPT: to accept incoming connections
    c22daa2ecf
  159. init: introduce I2P connectivity options
    Introduce two new options to reach the I2P network:
    
    * `-i2psam=<ip:port>` point to the I2P SAM proxy. If this is set then
      the I2P network is considered reachable and we can make outgoing
      connections to I2P peers via that proxy. We listen for and accept
      incoming connections from I2P peers if the below is set in addition to
      `-i2psam=<ip:port>`
    
    * `-i2pacceptincoming` if this is set together with `-i2psam=<ip:port>`
      then we accept incoming I2P connections via the I2P SAM proxy.
    76c35c60f3
  160. net: add I2P to the reachability map
    Update `CNetAddr::GetReachabilityFrom()` to recognize the I2P network so
    that we would prefer to advertise our I2P address to I2P peers.
    9559bd1404
  161. net: make outgoing I2P connections from CConnman 0635233a1e
  162. net: accept incoming I2P connections from CConnman b905363fa8
  163. net: recognize I2P from ParseNetwork() so that -onlynet=i2p works 0181e24439
  164. net: Do not skip the I2P network from GetNetworkNames()
    So that help texts include "i2p" in:
    * `./bitcoind -help` (in `-onlynet` description)
    * `getpeerinfo` RPC
    * `getnetworkinfo` RPC
    
    Co-authored-by: Jon Atack <jon@atack.com>
    a701fcf01f
  165. vasild force-pushed on Mar 1, 2021
  166. vasild commented at 5:30 PM on March 1, 2021: member

    f181f24ca...a701fcf01: pet the linter which seems to be upset by R"(foo "%s" bar")

  167. jonatack approved
  168. jonatack commented at 6:18 PM on March 1, 2021: member

    re-ACK a701fcf01f3ea9a12e869bfa52321302cf68351c reviewed diff per git range-diff ad89812 2a7bb34 a701fcf, debug built and launched bitcoind with i2pd v2.35 running a dual I2P+Torv3 service with the I2P config settings listed below (did not test onlynet=i2p); operation appears nominal (same as it has been these past weeks), and tested the bitcoind help outputs grepping for -i i2p and the rpc getpeerinfo and getnetworkinfo helps

    config settings

    i2psam=127.0.0.1:7656  # apt install i2pd / systemctl enable i2pd.service / systemctl start i2pd.service
    i2pacceptincoming=1  # default value
    debug=i2p
    

    tested with i2pd on Debian 5.10.13-1 (2021-02-06) x86_64 GNU/Linux

    $ i2pd --version
    i2pd version 2.35.0 (0.9.48)
    Boost version 1.74.0
    OpenSSL 1.1.1i  8 Dec 2020
    

    help output grepping for -i i2p

      -i2pacceptincoming
           If set and -i2psam is also set then incoming I2P connections are
           accepted via the SAM proxy. If this is not set but -i2psam is set
           then only outgoing connections will be made to the I2P network.
           Ignored if -i2psam is not set. Listening for incoming I2P
           connections is done through the SAM proxy, not by binding to a
           local address and port (default: 1)
    
      -i2psam=<ip:port>
           I2P SAM proxy to reach I2P peers and accept I2P connections (default:
           none)
    
      -onlynet=<net>
           Make outgoing connections only through network <net> (ipv4, ipv6, onion,
           i2p). Incoming connections are not affected by this option. This
           option can be specified multiple times to allow multiple
           networks. Warning: if it is used with non-onion networks and the
           -onion or -proxy option is set, then outbound onion connections
           will still be made; use -noonion or -onion=0 to disable outbound
           onion connections in this case.
    
      -debug=<category>
           Output debugging information (default: -nodebug, supplying <category> is
           optional). If <category> is not supplied or if <category> = 1,
           output all debugging information. <category> can be: net, tor,
           mempool, http, bench, zmq, walletdb, rpc, estimatefee, addrman,
           selectcoins, reindex, cmpctblock, rand, prune, proxy, mempoolrej,
           libevent, coindb, qt, leveldb, validation, i2p. This option can
           be specified multiple times to output multiple categories.
    

    relevant lines of RPC helps

    getpeerinfo
        "network" : "str",                (string) Network (ipv4, ipv6, onion, i2p, not_publicly_routable)
    
    getnetworkinfo
      "networks" : [                                     (json array) information per network
        {                                                (json object)
          "name" : "str",                                (string) network (ipv4, ipv6, onion, i2p)
    

    Edit: updated ACK commit hash from f181f24ca to a701fcf01 after checking diff, re-building and re-running bitcoind as a dual I2P+Torv3 service.

  169. laanwj commented at 10:38 AM on March 2, 2021: member

    re-ACK a701fcf01f3ea9a12e869bfa52321302cf68351c

  170. laanwj merged this on Mar 2, 2021
  171. laanwj closed this on Mar 2, 2021

  172. vasild deleted the branch on Mar 2, 2021
  173. sidhujag referenced this in commit 730aeb9a53 on Mar 2, 2021
  174. vasild commented at 4:40 PM on March 4, 2021: member

    @practicalswift

    I plan to add a fuzzing harness for the I2P Reply parsing code (unless @vasild plans to do it as part of this PR of course :)).

    I am adding some basic fuzzing of the i2p::sam::Session public interface using FuzzedSock (not to Reply()). Will open a PR soonish...

  175. practicalswift commented at 8:15 PM on March 4, 2021: contributor

    @vasild

    I plan to add a fuzzing harness for the I2P Reply parsing code (unless @vasild plans to do it as part of this PR of course :)).

    I am adding some basic fuzzing of the i2p::sam::Session public interface using FuzzedSock (not to Reply()). Will open a PR soonish...

    That's great news! Looking forward to reviewing it: don't hesitate to ping me when ready :)

  176. jonatack commented at 10:04 AM on March 5, 2021: member

    @vasild here are a couple more screenshots of being connected twice to the same I2P peer (one example of inbound+outbound, which can be persistent (and not unique to I2P peers IIRC, here we are each manually addnode-ing each other I believe), and one example of double inbound, which doesn't usually last more than ~5 minutes AFAICT but happens the most often, I see it a few times a day).

    The addrbind in every case is my local I2P address.

    Screenshot from 2021-03-05 10-58-35

    Screenshot from 2021-03-05 01-59-28

  177. vasild commented at 12:54 PM on March 8, 2021: member

    @practicalswift: fuzzing tests in #21387.

  178. vasild commented at 5:21 PM on March 8, 2021: member

    @jonatack

    one example of inbound+outbound, which can be persistent (and not unique to I2P peers

    Right. A->B and A<-B is not forbidden and can be done even with IPv4 addresses.

    and one example of double inbound

    I opened #21389 to track this.

  179. jonatack commented at 7:25 PM on March 8, 2021: member

    (did not test onlynet=i2p)

    Since writing that, I've been running onlynet=i2p with onlynet=onion and it seems to be working well.

  180. MarcoFalke referenced this in commit 18cd0888ef on Mar 19, 2021
  181. rebroad commented at 1:48 PM on May 3, 2021: contributor

    @jonatack those i2p pings look much higher than the tor pings. Is that normal? Does i2p offer any advantage over tor?

  182. jonatack commented at 2:05 PM on May 3, 2021: member

    @rebroad indeed (see #21261). An advantage is potentially better decentralization, network robustness and censorship resistance, e.g. I2P may be operational when Tor isn't or has degraded operation, like in January and February.

  183. vasild commented at 2:38 PM on May 3, 2021: member

    In addition, I2P connections have a "source address" - it is certain that the peer who connects from a given I2P address to us possesses the private key that corresponds to that I2P address. This can be used for white-listing "friends". It is a stronger guarantee than IP addresses (which can be spoofed by e.g. your ISP).

  184. in src/net.cpp:2217 in b905363fa8 outdated
    2212 | +
    2213 | +            continue;
    2214 | +        }
    2215 | +
    2216 | +        if (!advertising_listen_addr) {
    2217 | +            AddLocal(conn.me, LOCAL_BIND);
    


    sdaftuar commented at 1:35 PM on May 4, 2021:

    I don't entirely understand how these enums (LOCAL_BIND, LOCAL_MANUAL, etc) are meant to be used, but I wonder if this should be LOCAL_MANUAL instead? That seems to be what we use for listening on an onion address: https://github.com/bitcoin/bitcoin/blob/0ca8b7e7ecd5bc537fbc1e372f6755a34a136f7f/src/torcontrol.cpp#L354

    I noticed that when I'm running with -externalip, I don't get my i2p address listed as a local address (presumably because fDiscover gets defaulted to false and then anything less than LOCAL_MANUAL is ignored in AddLocal()), even though my onion address is unaffected by the setting. Changing this to LOCAL_MANUAL seems to fix this issue.


    vasild commented at 2:57 PM on May 4, 2021:

    I played with the LOCAL_* enums, but I don't remember why I chose LOCAL_BIND :-( I wonder why AddLocal() induced by -externalip did not work:

    https://github.com/bitcoin/bitcoin/blob/0ca8b7e7ecd5bc537fbc1e372f6755a34a136f7f/src/init.cpp#L1304-L1307


    sdaftuar commented at 2:59 PM on May 4, 2021:

    Sorry I should have been more clear -- I was using -externalip with an ipv4 address (this node is listening on an ipv4 address, onion address, and i2p address). However I noticed that with -externalip enabled, the AddLocal for the i2p address didn't work.

    Presumably if I set -discover=1 explicitly then it would have worked? But I was just surprised that there's a difference between what we do for onion vs i2p.


    vasild commented at 10:58 AM on May 11, 2021:

    Presumably if I set -discover=1 explicitly then it would have worked?

    Yes.

    Fixed in #21914.

  185. laanwj referenced this in commit 5c4f0c4d46 on Jun 14, 2021
  186. sidhujag referenced this in commit b9e1e110ed on Jun 14, 2021
  187. luke-jr referenced this in commit dce01c8bad on Jun 27, 2021
  188. Fabcien referenced this in commit 4557b8ebb2 on Feb 10, 2022
  189. Fabcien referenced this in commit c577087f76 on Feb 10, 2022
  190. Fabcien referenced this in commit b4f3921ff5 on Feb 10, 2022
  191. Fabcien referenced this in commit fb406d6140 on Feb 10, 2022
  192. Fabcien referenced this in commit 1e55ff33b8 on Feb 10, 2022
  193. Fabcien referenced this in commit 2dd02eaa67 on Feb 10, 2022
  194. Fabcien referenced this in commit aff7e41f00 on Feb 10, 2022
  195. Fabcien referenced this in commit 60329d3282 on Feb 11, 2022
  196. Fabcien referenced this in commit c1e9bd7401 on Feb 11, 2022
  197. Fabcien referenced this in commit 3526cd88a6 on Feb 11, 2022
  198. Fabcien referenced this in commit bdcf5ed386 on Feb 15, 2022
  199. Fabcien referenced this in commit 9f22e70a42 on Feb 15, 2022
  200. Fabcien referenced this in commit 795cafd9a4 on Feb 15, 2022
  201. DrahtBot locked this on Aug 18, 2022

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-05-02 18:14 UTC

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