### FEATURE REQUEST

Currently, when a bitcoin node is set up with a connection to both TOR and normal IPv4/6 internet, the 8 outbound-only connection slots, almost always get filled with nodes connecting over IP.
Adding a config option, which would try to ballance these connections based on what kind of network they go through, would be benefficial in many ways:

1. It would add edges between bitcoin network on TOR and normal internet, reducing delays, and the risks associated with an attacker isolating a part of TOR-bitcoin-network from the rest of the world
(Or an ISP/government man-in-the-middling all the normal IP connections)

2. It would help hide/annonymise normal user's transactions from his/her ISP, by mixing them with TOR-outbound ones

3. It would reduce the stress on normal general purpose TOR exit nodes, as users would more likely/reliably connect to TOR-IPv4/6 bitcoin nodes instead of exiting into normal internet first, and then connecting to default IPv4/6-only bitcoin nodes

I understand it is possible to create such bridges already, by forcing connections to TOR-only nodes, or by just running a node with lots of inbound slots, but I think the proposed option, would greatly increase the number of such relays, and remove the need for user to maintain a TOR-node whitelist, by handing this work off to normal bitcoind connection finding algorithm.

This could be implemented as a minimum number of connections for each network, or just a simple evening boolean switch. (Which could be enabled by default for bitcoind installs with TOR connectivity)

In the future, if bitcoin was to support a new network type (for example cjdns/I2P/GNUnet), this option would help establish a presence on the new network faster

bitcoind: 0.15
e Tor v3 addresses because it requires
     * ADDRv2 (BIP155) encoding.
     */
    bool IsAddrCompatible(const CAddress& addr) const
    {
        return m_wants_addrv2 || addr.IsAddrV1Compatible();
    }
    void PushAddress(const CAddress& _addr, FastRandomContext &insecure_rand)
    {
        // 
        // 
        // 
        assert(m_addr_known);
        if (_addr.IsValid() && m_addr_known->contains(_addr.GetKey()) && IsAddrCompatible(_addr)) {
            if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
                vAddrToSend[insecure_rand.randrange(vAddrToSend.size())] = _addr;
            } else {
                vAddrToSend.push_back(_addr);
            }
        }
    }
    void AddKnownTx(const uint256& hash)
    {
        if (m_tx_relay = nullptr) {
            LOCK(m_tx_relay->cs_tx_inventory);
            m_tx_relay->filterInventoryKnown.insert(hash);
        }
    }
    void PushTxInventory(const uint256& hash)
    {
        if (m_tx_relay == nullptr) return;
        LOCK(m_tx_relay->cs_tx_inventory);
        if (m_tx_relay->filterInventoryKnown.contains(hash)) {
            m_tx_relay->setInventoryTxToSend.insert(hash);
        }
    }
    void CloseSocketDisconnect();
    void copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap);
    ServiceFlags GetLocalServices() const
    {
        return nLocalServices;
    }
    std::string GetAddrName() const;
    //
    void MaybeSetAddrName(const std::string& addrNameIn);
    std::string ConnectionTypeAsString() const { return ::ConnectionTypeAsString(m_conn_type); }
    /*
    void PongReceived(std::chrono::microseconds ping_time) {
        m_last_ping_time = ping_time;
        m_min_ping_time = std::min(m_min_ping_time.load(), ping_time);
    }
private:
    const NodeId id;
    const uint64_t nLocalHostNonce;
    const ConnectionType m_conn_type;
    std::atomic<int> m_greatest_common_version{INIT_PROTO_VERSION};
    //
    //
    //
    //
    //
    //
    //
    //
    //
    //
    //
   