### 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
       data_hash.SetNull();
        hasher.Reset();
    }
public:
    V1TransportDeserializer(const CChainParams& chain_params, const NodeId node_id, int nTypeIn, int nVersionIn)
        : m_chain_params(chain_params),
          m_node_id(node_id),
          hdrbuf(nTypeIn, nVersionIn),
          vRecv(nTypeIn, nVersionIn)
    {
        Reset();
    }
    bool Complete() const override
    {
        if (in_data)
            return false;
        return (hdr.nMessageSize == nDataPos);
    }
    void SetVersion(int nVersionIn) override
    {
        hdrbuf.SetVersion(nVersionIn);
        vRecv.SetVersion(nVersionIn);
    }
    int Read(Span<const uint8_t>& msg_bytes) override
    {
        int ret = in_data ? readData(msg_bytes) : readHeader(msg_bytes);
        if (ret < 0) {
            Reset();
        } else {
            msg_bytes = msg_bytes.subspan(ret);
        }
        return ret;
    }
    std::optional<CNetMessage> GetMessage(std::chrono::microseconds time, uint32_t& out_err_raw_size) override;
};
/** The TransportSerializer prepares messages for the network transport
 */
class TransportSerializer {
public:
    // 
    virtual void prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) = 0;
    virtual ~TransportSerializer() {}
};
class V1TransportSerializer  : public TransportSerializer {
public:
    void prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) override;
};
/** Information about a peer */
class CNode
{
    friend class CConnman;
    friend struct ConnmanTestMsg;
public:
    std::unique_ptr<TransportDeserializer> m_deserializer;
    std::unique_ptr<TransportSerializer> m_serializer;
    NetPermissionFlags m_permissionFlags{PF_NONE};
    std::atomic<ServiceFlags> nServices{NODE_NONE};
    SOCKET hSocket GUARDED_BY(cs_hSocket);
    /*
    size_t nSendSize GUARDED_BY(cs_vSend){0};
    /*
    size_t nSendOffset GUARDED_BY(cs_vSend){0};
    uint64_t nSendBytes GUARDED_BY(cs_vSend){0};
    std::dequ